Initial commit 92/169792/1
authorWootak Jung <wootak.jung@samsung.com>
Fri, 9 Feb 2018 06:16:55 +0000 (15:16 +0900)
committerWootak Jung <wootak.jung@samsung.com>
Fri, 9 Feb 2018 06:16:55 +0000 (15:16 +0900)
Change-Id: Ic967a26a6a1f1bbcefbe823c50dabbb6e33da784

193 files changed:
ChangeLog
Makefile
README
dispatcher.c
jim/AUTHORS [changed mode: 0644->0755]
jim/BUGS [new file with mode: 0755]
jim/DEVELOPING [new file with mode: 0755]
jim/LICENSE [changed mode: 0644->0755]
jim/Makefile.in
jim/README [changed mode: 0644->0755]
jim/README.extensions [new file with mode: 0755]
jim/README.metakit [new file with mode: 0755]
jim/README.namespaces [new file with mode: 0755]
jim/README.oo [new file with mode: 0755]
jim/README.sqlite [new file with mode: 0755]
jim/README.usb_modeswitch [deleted file]
jim/README.utf-8 [new file with mode: 0755]
jim/STYLE [new file with mode: 0755]
jim/TODO [new file with mode: 0755]
jim/Tcl_shipped.html [new file with mode: 0755]
jim/UnicodeData.txt [new file with mode: 0755]
jim/auto.def [changed mode: 0644->0755]
jim/autosetup/LICENSE [changed mode: 0644->0755]
jim/autosetup/README.autosetup [changed mode: 0644->0755]
jim/autosetup/autosetup
jim/autosetup/cc-db.tcl [new file with mode: 0755]
jim/autosetup/cc-lib.tcl [changed mode: 0644->0755]
jim/autosetup/cc-shared.tcl [changed mode: 0644->0755]
jim/autosetup/cc.tcl [changed mode: 0644->0755]
jim/autosetup/config.guess
jim/autosetup/config.sub
jim/autosetup/default.auto [new file with mode: 0755]
jim/autosetup/find-tclsh
jim/autosetup/jimsh0.c [new file with mode: 0644]
jim/autosetup/local.tcl [new file with mode: 0755]
jim/autosetup/system.tcl [changed mode: 0644->0755]
jim/autosetup/test-tclsh [changed mode: 0644->0755]
jim/bench.tcl [new file with mode: 0755]
jim/binary.tcl [new file with mode: 0755]
jim/bootstrap.tcl [changed mode: 0644->0755]
jim/build-jim-ext.in [new file with mode: 0755]
jim/configure
jim/configure.ac [changed mode: 0644->0755]
jim/freebsd/andrew.txt [changed mode: 0644->0755]
jim/freebsd/clemens.txt [changed mode: 0644->0755]
jim/freebsd/duane.txt [changed mode: 0644->0755]
jim/freebsd/oharboe.txt [changed mode: 0644->0755]
jim/freebsd/pat.txt [changed mode: 0644->0755]
jim/freebsd/salvatore.txt [changed mode: 0644->0755]
jim/freebsd/uwe.txt [changed mode: 0644->0755]
jim/glob.tcl [changed mode: 0644->0755]
jim/initjimsh.tcl [changed mode: 0644->0755]
jim/jim-aio.c
jim/jim-array.c
jim/jim-clock.c
jim/jim-config.h.in [changed mode: 0644->0755]
jim/jim-eventloop.c
jim/jim-eventloop.h
jim/jim-exec.c
jim/jim-file.c
jim/jim-format.c
jim/jim-history.c [new file with mode: 0644]
jim/jim-interactive.c
jim/jim-load.c
jim/jim-mk.cpp [new file with mode: 0644]
jim/jim-namespace.c [new file with mode: 0644]
jim/jim-nvp.c [deleted file]
jim/jim-nvp.h [deleted file]
jim/jim-pack.c
jim/jim-package.c
jim/jim-posix.c
jim/jim-readdir.c
jim/jim-readline.c
jim/jim-regexp.c
jim/jim-sdl.c
jim/jim-signal.c
jim/jim-signal.h
jim/jim-sqlite3.c [new file with mode: 0644]
jim/jim-subcmd.c
jim/jim-subcmd.h
jim/jim-syslog.c
jim/jim-tclprefix.c [new file with mode: 0644]
jim/jim-win32.c [new file with mode: 0644]
jim/jim-win32compat.c [new file with mode: 0644]
jim/jim-win32compat.h
jim/jim.c
jim/jim.h
jim/jim_tcl.txt [new file with mode: 0755]
jim/jimautoconf.h.in [deleted file]
jim/jimregexp.c
jim/jimregexp.h
jim/jimsh.c
jim/linenoise.c
jim/linenoise.h
jim/make-bootstrap-jim
jim/make-c-ext.tcl [changed mode: 0644->0755]
jim/make-index
jim/make-load-static-exts.tcl [changed mode: 0644->0755]
jim/make-release.sh [new file with mode: 0755]
jim/nshelper.tcl [new file with mode: 0755]
jim/oo.tcl [new file with mode: 0755]
jim/parse-unidata.tcl [changed mode: 0644->0755]
jim/regtest.tcl [changed mode: 0644->0755]
jim/rlprompt.tcl [changed mode: 0644->0755]
jim/stdlib.tcl [changed mode: 0644->0755]
jim/tcl.license.terms [changed mode: 0644->0755]
jim/tclcompat.tcl [changed mode: 0644->0755]
jim/tests/Makefile [new file with mode: 0755]
jim/tests/alias.test [new file with mode: 0755]
jim/tests/apply.test [new file with mode: 0755]
jim/tests/applyns.test [new file with mode: 0755]
jim/tests/array.test [new file with mode: 0755]
jim/tests/binary.test [new file with mode: 0755]
jim/tests/break.tcl [new file with mode: 0755]
jim/tests/concat.test [new file with mode: 0755]
jim/tests/dict.test [new file with mode: 0755]
jim/tests/dict2.test [new file with mode: 0755]
jim/tests/dummy.tcl [new file with mode: 0755]
jim/tests/error.test [new file with mode: 0755]
jim/tests/errors.tcl [new file with mode: 0755]
jim/tests/event.test [new file with mode: 0755]
jim/tests/exec.test [new file with mode: 0755]
jim/tests/exec2.test [new file with mode: 0755]
jim/tests/exists.test [new file with mode: 0755]
jim/tests/exitpackage.tcl [new file with mode: 0755]
jim/tests/expand.test [new file with mode: 0755]
jim/tests/expr-base.test [new file with mode: 0755]
jim/tests/expr-new.test [new file with mode: 0755]
jim/tests/expr-old.test [new file with mode: 0755]
jim/tests/expr.test [new file with mode: 0755]
jim/tests/exprsugar.test [new file with mode: 0755]
jim/tests/filecopy.test [new file with mode: 0755]
jim/tests/filedir.test [new file with mode: 0755]
jim/tests/filejoin.test [new file with mode: 0755]
jim/tests/for.test [new file with mode: 0755]
jim/tests/format.test [new file with mode: 0755]
jim/tests/glob.test [new file with mode: 0755]
jim/tests/infoframe.test [new file with mode: 0755]
jim/tests/jim.test [new file with mode: 0755]
jim/tests/linsert.test [new file with mode: 0755]
jim/tests/list.test [new file with mode: 0755]
jim/tests/loop.test [new file with mode: 0755]
jim/tests/lrange.test [new file with mode: 0755]
jim/tests/lreplace.test [new file with mode: 0755]
jim/tests/lsearch.test [new file with mode: 0755]
jim/tests/lsort.test [new file with mode: 0755]
jim/tests/lsortcmd.test [new file with mode: 0755]
jim/tests/misc.test [new file with mode: 0755]
jim/tests/namespace.test [new file with mode: 0755]
jim/tests/parse.test [new file with mode: 0755]
jim/tests/perf.test [new file with mode: 0755]
jim/tests/pid.test [new file with mode: 0755]
jim/tests/prefix.test [new file with mode: 0755]
jim/tests/proc-new.test [new file with mode: 0755]
jim/tests/proc.test [new file with mode: 0755]
jim/tests/procref.test [new file with mode: 0755]
jim/tests/regcount.test [new file with mode: 0755]
jim/tests/regexp.test [new file with mode: 0755]
jim/tests/regexp2.test [new file with mode: 0755]
jim/tests/regmin.test [new file with mode: 0755]
jim/tests/rename.test [new file with mode: 0755]
jim/tests/return-break.tcl [new file with mode: 0755]
jim/tests/return.test [new file with mode: 0755]
jim/tests/scan.test [new file with mode: 0755]
jim/tests/signal.test [new file with mode: 0755]
jim/tests/stacktrace.test [new file with mode: 0755]
jim/tests/string.test [new file with mode: 0755]
jim/tests/stringmatch.test [new file with mode: 0755]
jim/tests/subst.test [new file with mode: 0755]
jim/tests/tailcall.test [new file with mode: 0755]
jim/tests/testing.tcl [new file with mode: 0755]
jim/tests/testio.in [new file with mode: 0755]
jim/tests/timer.test [new file with mode: 0755]
jim/tests/tree.test [new file with mode: 0755]
jim/tests/try.test [new file with mode: 0755]
jim/tests/uplevel.test [new file with mode: 0755]
jim/tests/upvar.test [new file with mode: 0755]
jim/tests/utf8.test [new file with mode: 0755]
jim/tests/utftcl.test [new file with mode: 0755]
jim/tests/util.test [new file with mode: 0755]
jim/tests/while.test [new file with mode: 0755]
jim/tree.tcl [changed mode: 0644->0755]
jim/utf8.c
jim/utf8.h
packaging/usb-modeswitch.spec
usb_modeswitch.1 [changed mode: 0644->0755]
usb_modeswitch.c
usb_modeswitch.conf
usb_modeswitch.h
usb_modeswitch.sh
usb_modeswitch.tcl
usb_modeswitch@.service [changed mode: 0644->0755]
usb_modeswitch_dispatcher.1 [changed mode: 0644->0755]

index c71132b..e83abdb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,37 +2,6 @@
 History of USB_ModeSwitch
 =========================
 
-Version 2.2.6, 2015/11/01
-    Renamed function abort(), avoiding possible conflicts in static builds
-    with libjim (thanks, Gustavo Zacharias); removed storage class check of
-    interface 0 from dispatcher, enabling new multi-config devices in data
-    package 20151101
-Version 2.2.5, 2015/07/16
-    Fixed bug in configuration check, possibly leading to segfault (thanks,
-    Leonid Lisovskiy); fixed Pantech commandline parameter evaluation (was
-    not working at all); added driver unbind step via sysfs in wrapper,
-    getting rid of the USB subsystem complaint "interface 0 claimed by
-    usb-storage while 'usb_modeswitch' <does this and that>"
-Version 2.2.4, 2015/07/14
-    Fixed buggy check of USB configuration selection (possibly leading
-    to segfault), tested with Alcatel X602D; removed call to 'libusb_strerror'
-    from libusb initialization - not available in earlier libusb1 versions
-Version 2.2.3, 2015/06/29
-    Fixed problem arising with systemd version 221 (220 untested), which
-    affects starting the usb_modeswitch systemd unit from the sh script
-    (reported by Archlinux users)
-Version 2.2.2, 2015/06/27
-    Added catch for libusb init error (thanks, Henrik Gustafsson); removed
-    global function result variable; added catch for USB configuration
-    read error (both thanks to "otila"); fixed wrapper script where port
-    search for symlinking modem port was broken ("/dev/gsmmodem"); changed
-    PantechMode parameter to represent different targets; added global
-    config option to disable MBIM checking and setting alltogether (request
-    from "kai"); changed udev sh script so that systemd processing takes
-    precedence over upstart; changed systemd template unit parameter to
-    avoid escaping problems
-Version 2.2.1, 2015/01/15
-    Fixed unreliable switching function for Cisco AM10
 Version 2.2.0, 2014/05/29
     Introduction of parameter "HuaweiNewMode", wrapping the standard bulk
     message for all newer Huawei devices; support for generic fall-back
@@ -72,7 +41,7 @@ Version 2.0.0, 2013/09/01
     install the matching service file; you may want to adapt it better to
     your respective system, possibly adding dependencies/targets to the
     services. Note that the udev starter script usb_modeswitch.sh also
-    checks for the existence of the service/unit files
+    checks for the existence of the service files
 Version 1.2.7, 2013/08/07
     Two new dedicated control message functions to support Pantech LTE
     (thanks to Adam Goode) and Blackberry Q10/Z10 (thanks to Daniel Mende)
index 00043d3..f12f69f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 PROG        = usb_modeswitch
-VERS        = 2.2.6
+VERS        = 2.2.0
 CC          ?= gcc
 CFLAGS      += -Wall
 LIBS        = `pkg-config --libs --cflags libusb-1.0`
@@ -85,7 +85,7 @@ install-common: $(PROG) usb_modeswitch_dispatcher
        install -D --mode=755 usb_modeswitch_dispatcher $(SBINDIR)/usb_modeswitch_dispatcher
        install -d $(DESTDIR)/var/lib/usb_modeswitch
        test -d $(UPSDIR) -a -e /sbin/initctl && install --mode=644 usb-modeswitch-upstart.conf $(UPSDIR) || test 1
-       test -d $(SYSDIR) -a \( -e /usr/bin/systemctl -o -e /bin/systemctl \) && install --mode=644 usb_modeswitch@.service $(SYSDIR) || test 1
+       test -d $(SYSDIR) -a -e /usr/bin/systemctl && install --mode=644 usb_modeswitch@.service $(SYSDIR) || test 1
 
 install: install-script
 
diff --git a/README b/README
index 1c0294e..db5eed5 100644 (file)
--- a/README
+++ b/README
@@ -7,19 +7,18 @@ http://www.draisberghof.de/usb_modeswitch
 What it is
 ==========
 
-USB_ModeSwitch is - hardly surprising -  a mode switching tool for controlling
-USB devices with multiple "modes". Now, what does THAT mean?
+USB_ModeSwitch is (surprise!) a small mode switching tool for controlling
+"flip flop" (multiple mode) USB devices.
 
 More and more USB devices have their MS Windows drivers onboard; when plugged
 in for the first time they act like a flash storage and offer their driver
 installation from there.
 After installation (and on every consecutive plugging) the driver switches the
-mode internally by sending a certain command sequence; the storage device
-vanishes (in most cases) and a different device - like a USB modem - shows up.
-To the host, this is like unplugging one device and then plugging annother.
+mode internally, the storage device vanishes (in most cases), and a new device
+(like an USB modem) shows up.
 
 At first this feature appeared on devices with cell phone chipsets, presumably
-because some of them were already able to change the mode of their USB port
+because some of them were able to change the mode of their USB port anyway
 from storage to communication - so why not make use of this in a modem stick?
 Modem maker "Option" calls that feature "ZeroCD (TM)" since it eliminates the
 need for shipping a separate driver carrier.
@@ -27,33 +26,27 @@ need for shipping a separate driver carrier.
 In the beginning, nothing of this was documented in any form and there was
 hardly any Linux/Unix support available.
 On the good side, most of the known devices are working out of the box in all
-modes with available Linux modules like "usb-storage" or serial USB drivers.
+modes with the available Linux modules like "usb-storage" or serial USB drivers.
 That leaves only the problem of the mode-switching from storage to whatever
 the thing is supposed to do.
 
-Fortunately there are things like human smartness, USB sniffing programs and
-LibUSB. The obvious way is to eavesdrop on the communication of the MS Windows
-driver, to isolate the command or action that does the switching, and then re-
-play the same sequence in a non-Windows system.
+Fortunately there are things like human intelligence, USB sniffing programs and
+"libusb". It is possible to eavesdrop the communication of the MS Windows
+driver, to isolate the command or action that does the switching, and to replay
+the same sequence in the Unix system.
 
-In theory, this task could also be handled on the kernel driver level, but a
-userspace program is much more flexible and can easily be disabled if access
-to the initial mode of those devices should be desired. There has been a
-principle decision by kernel developers to keep mode-switching outside of the
-kernel.
+USB_ModeSwitch makes this process easy to handle by taking the relevant para-
+meters from a configuration file and doing all the initialization and communi-
+cation stuff, with heavy help from "libusb".
 
-So USB_ModeSwitch has evolved to make this process easy to handle by taking the
-relevant parameters from configuration files and handling all initialization
-and communication business, with essential help from "libusb".
-
-In Linux and friends it is intended to work automatically - via udev events
+In Linux and friends it is intended to be used automatically - via udev events
 and rules - and doing the mode switch without any user interaction.
-However, the core program should be as portable als libusb itself; it does not
+However, the core program should be as portable als libusb itself; it does not
 rely on specific Linux features.
-It can also be run as an interactive command line tool, particularly useful when
-trying to tinker with hitherto unknown devices.
+It can be run as an interactive command line tool, particularly useful when trying
+to manage hitherto unknown devices.
 
-We have already collected a wide range of information on how to mode-switch all
+We have already collected a wide range of information on how to switch all
 sorts of devices. If you run into a new one that is unknown yet, don't despair:
 we can find out what you need to do!
 
@@ -61,10 +54,6 @@ we can find out what you need to do!
 How to install
 ==============
 
-If you only need the core C program, just run "make". All further steps de-
-scribed below are referring to a common, fairly current Linux system where
-USB_ModeSwitch is expected to do its work automatically.
-
 !! You need the usb-modeswitch-data package from the same source as this !!
 
 If you have an earlier version installed, de-installation is recommended ("make
@@ -73,9 +62,8 @@ old files might be orphaned but will not do any harm.
 
 The main prerequisite for installing from source is the development package for
 "libusb". It may be called "libusb-dev" or similar in your distribution. From
-usb_modeswitch 2.0.0 on, it should have an "1.x" in the name to reflect the change
-to libusb-1. There are also variants around called "libusbx" if libusb-1 is not
-available on your distribution.
+usb_modeswitch 2.0.0 it should have an "1.x" in the name to reflect the change
+to libusb-1.
 
 To install the tool set, unpack and run the install command (see below) in the
 newly created directory.
@@ -155,8 +143,7 @@ Again, remember that the rules file and the default device config folder
 
 
 ##########
-Important: libusb programs - like this tool - want to be run with administrative
-privileges (as root or with sudo)!
+Important: libusb programs - like this tool - want to be run as root!
 ##########
 
 
@@ -164,8 +151,8 @@ privileges (as root or with sudo)!
 Known working hardware, Troubleshooting
 =======================================
 
-Please go to the homepage (see link at the top). Read carefully.
-For support questions use ONLY public posts in the forum.
+Please see the homepage. Read carefully.
+For support questions use ONLY the forum.
 
 
 
@@ -188,8 +175,8 @@ forum (see above) or send it to the author (see below)!
 Whodunit
 ========
 
-Copyright 2007 - 2015 Josua Dietze (for non-support notifications write a personal
-message through the forum to "Josh"; everything else only in a forum thread)
+Copyright 2007 - 2014 Josua Dietze (mail to "usb_admin" at the domain
+"draisberghof.de" or write a personal message through the forum to "Josh")
 
  !!! NO SUPPORT QUESTIONS VIA E-MAIL, use the forum !!!
 
@@ -211,9 +198,6 @@ Config file parsing code borrowed from:
 Hexstr2bin function borrowed from:
  Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c")
 
-Indispensable help with device research and compilation:
- Lars Melin
-
 Code, fixes and ideas contributed by:
  Aki Makkonen
  Denis Sutter
@@ -267,4 +251,4 @@ Or find it as the file COPYING in this folder.
 
 
 
-Last revised: 2015-06-27, Josua Dietze
+Last revised: 2014-01-28, Josua Dietze
index 49ba85c..0291bd4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2015 Josua Dietze, usb_modeswitch version 2.2.2
+ * Copyright (c) 2011-2014 Josua Dietze, usb_modeswitch version 2.1.1
  * Contains code under
  * Copyright (c) 2010 Wojciech A. Koszek <wkoszek@FreeBSD.org>
  * All rights reserved.
old mode 100644 (file)
new mode 100755 (executable)
index 73413a5..052babb
@@ -29,13 +29,13 @@ Also the following ideas are due to the following authors:
   current-iteartion result, providing in one command the power of
   [map] and [filter] together.
 
-ChangeLog committers to be identified. Tentative list:  
+
+ChangeLog committers to be identified. Tentative list:
+
 antirez - Salvatore Sanfilippo <antirez@gmail.com>
-patthoyts - Pat Thoyts <patthoyts@users.sf.net> 
-oharboe - Ã˜yvind Harboe - soyvind.harboe@zylin.com
-Andrew Lunn <andrew@lunn.ch> 
+patthoyts - Pat Thoyts <patthoyts@users.sf.net>
+oharboe - Ã˜yvind Harboe - soyvind.harboe@zylin.com
+Andrew Lunn <andrew@lunn.ch>
 Duane Ellis <openocd@duaneellis.com>
 Uwe Klein <uklein@klein-messgeraete.de>
 Clemens Hintze ml-jim@qiao.in-berlin.de aka chi
diff --git a/jim/BUGS b/jim/BUGS
new file mode 100755 (executable)
index 0000000..b084318
--- /dev/null
+++ b/jim/BUGS
@@ -0,0 +1,4 @@
+Known bugs
+==========
+
+None!
diff --git a/jim/DEVELOPING b/jim/DEVELOPING
new file mode 100755 (executable)
index 0000000..835cd0b
--- /dev/null
@@ -0,0 +1,93 @@
+Working on Jim
+==============
+
+Jim's sources are kept in Git Version Control System. Global repository of
+Jim project is placed on this Web site:
+
+        http://repo.or.cz/w/jimtcl.git
+
+There are two ways of contributing to Jim project. First is suited for
+one-time fixes and small corrections. The second is more appropriate
+for long-term contributors interested in Jim internals.
+
+Small changes
+=============
+
+For small modifications, procedure of preparing a traditional 'patch'
+is enough. In order to prepare a patch, you first have to obtain the
+most recent copy of Jim Tcl. This can be done with following command:
+
+        git clone http://repo.or.cz/r/jimtcl.git
+
+After entering newly created directory you can easily correct/fix/modify
+files. Once finished, patch can be easily generated:
+
+        git diff > my_patch_fixing_x_y.patch
+
+If working without Git system, you'll have to backup files first, modify
+the original files and obtain a patch manually:
+
+        cp jim.c jim.c.ORIGINAL
+
+        [...] <- modifications go here
+
+        diff -u jim.c.ORIGINAL jim.c > my_patch_fixing_z.patch
+
+Bigger changes
+==============
+
+In order to help extending and correcting Jim in a long term basis, one
+needs to create separate fork of Jim project and maintain his changes in a
+separate copy of a repository.
+
+By visiting this site, you'll have a chance to fork a project. This can
+be easily done with "fork" link. Form that will show up next refers to
+the project that is about to be started. The only thing that has to be
+taken care of is the project mode -- it should be "push mode".
+
+Once the project is created one must add a user that will actually
+start commiting new files to the repo. It can also be done through the
+WWW interface, so nothing more is necessary.
+
+Once finished with setting up a project on the WWW panel, one can
+start playing with actual import of the files. In order to obtain copy
+of Jim sources, we have to clone the repository:
+
+        git clone http://repo.or.cz/r/jimtcl.git
+
+Now, we must push fresh copy of Jim to your project URL:
+
+        git push <URL> master
+
+So for example for me it was:
+
+        git push ssh://repo.or.cz/srv/git/jimtcl/wkoszek.git master
+
+In order to add file we type "git add <file>".  For remove, we do "git rm
+<file>".  To remove all local changes that aren't in a repository you do "git
+reset --hard HEAD".  Once inserted, files have to be commited with "git commit
+-a".  Once done with commits for today, "git push" can be used to propagate
+changes from your local disk to the remote repository.
+
+Right now you can verify whether this works by trying to clone your
+project's repository somewhere else, this time using anonymount HTTP
+access:
+
+        git clone http://repo.or.cz/r/jimtcl/wkoszek.git
+
+Review, testing and publishing
+==============================
+
+Notification of work that can be considered finished is more than welcome on
+Jim-devel mailing list:
+
+        http://jim.tcl.tk:8080/cgi-bin/mailman/listinfo/jim-devel
+
+Patches prepared with the procedures presented abore are welcome. Before
+submitting patches, you can verify that your changes didn't bring any
+regressions to the Jim. In order to do so, sample regression tests have
+been implemented. You can execute them by typing:
+
+        make test
+
+All tests should succeed.
old mode 100644 (file)
new mode 100755 (executable)
index d5b9ecb..22568e5
@@ -5,8 +5,8 @@ under following license:
  *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> 
- * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
+ * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
+ * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
  * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
  * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
  * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
@@ -14,18 +14,18 @@ under following license:
  * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
  * Copyright 2009 Zachary T Welch zw@superlucidity.net
  * Copyright 2009 David Brownell
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above
  *    copyright notice, this list of conditions and the following
  *    disclaimer in the documentation and/or other materials
  *    provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
@@ -38,7 +38,7 @@ under following license:
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
+ *
  * The views and conclusions contained in the software and documentation
  * are those of the authors and should not be interpreted as representing
  * official policies, either expressed or implied, of the Jim Tcl Project.
index 0191c83..b27ecd1 100644 (file)
@@ -1,5 +1,5 @@
 # Tools
-CC ?= @CCACHE@ @CC@
+CC = @CCACHE@ @CC@
 CXX = @CCACHE@ @CXX@
 RANLIB = @RANLIB@
 AR = @AR@
@@ -9,12 +9,20 @@ STRIP = @STRIP@
 
 SH_CFLAGS ?= @SH_CFLAGS@
 SH_LDFLAGS ?= @SH_LDFLAGS@
+@if SH_SOPREFIX
+SH_LDFLAGS += @SH_SOPREFIX@libjim@LIBSOEXT@
+@endif
 SHOBJ_CFLAGS ?= @SHOBJ_CFLAGS@
+@if JIM_STATICLIB
 SHOBJ_LDFLAGS ?= @SHOBJ_LDFLAGS@
-CFLAGS = @CFLAGS@
-CXXFLAGS = @CXXFLAGS@
+@else
+SHOBJ_LDFLAGS ?= @SHOBJ_LDFLAGS_R@
+@endif
+CFLAGS = @CFLAGS@ @CCOPTS@ @CPPFLAGS@
+CXXFLAGS = @CXXFLAGS@ @CXXOPTS@
 LDFLAGS = @LDFLAGS@
 LDLIBS += @LDLIBS@
+LIBS += @LIBS@
 exec_prefix ?= @exec_prefix@
 prefix ?= @prefix@
 
@@ -29,11 +37,11 @@ VPATH := @srcdir@
 @if JIM_STATICLIB
 LIBJIM := libjim.a
 @else
-LIBJIM := libjim.so
+LIBJIM := libjim@LIBSOEXT@
 SH_LIBJIM := $(LIBJIM)
 CC += $(SH_CFLAGS)
 CXX += $(SH_CFLAGS)
-DEF_LD_PATH := @LD_LIBRARY_PATH@=`pwd` 
+DEF_LD_PATH := @LD_LIBRARY_PATH@="@builddir@:$(@LD_LIBRARY_PATH@)"
 @endif
 
 @if HAVE_CXX_EXTENSIONS
@@ -47,50 +55,66 @@ OBJS := _load-static-exts.o jim-subcmd.o jim-interactive.o jim-format.o jim.o ut
 
 JIMSH := jimsh@EXEEXT@
 
+@if JIM_INSTALL
+INSTALL_DATA_DIR ?= mkdir -p
+INSTALL_DATA ?= cp
+INSTALL_PROGRAM ?= cp
+@endif
+
 all: $(JIMSH) @C_EXT_SHOBJS@
 
 # Create C extensions from pure Tcl extensions
 .SUFFIXES: .tcl
 .tcl.o:
-       @tclsh@ @srcdir@/make-c-ext.tcl $< >_$*.c || ( rm _$*.c; exit 1)
-       $(CC) $(CFLAGS) -c -o $@ _$*.c || ( rm _$*.c; exit 1)
-       @rm -f _$*.c
+       @tclsh@ @srcdir@/make-c-ext.tcl $< >_$*.c
+       $(CC) $(CFLAGS) -c -o $@ _$*.c
 
 docs: Tcl.html
 
+@if JIM_DOCS
+install-docs: docs
+       $(INSTALL_DATA_DIR) $(DESTDIR)$(prefix)/doc/jim
+       $(INSTALL_DATA) Tcl.html $(DESTDIR)$(prefix)/doc/jim
+@else
+install-docs:
+@endif
+
 $(JIMSH): $(LIBJIM) jimsh.o initjimsh.o
-       $(JIMSH_CC) @SH_LINKFLAGS@ $(LDFLAGS) -o $@ jimsh.o initjimsh.o $(LIBJIM) $(LDLIBS)
+       $(JIMSH_CC) @SH_LINKFLAGS@ $(LDFLAGS) -o $@ jimsh.o initjimsh.o $(LIBJIM) $(LDLIBS) $(LIBS)
 
 @if JIM_INSTALL
-install: all docs @TCL_EXTS@ install-exec
-       mkdir -p $(DESTDIR)$(prefix)/lib/jim
-       cp $(LIBJIM) $(DESTDIR)$(prefix)/lib
-       cp @srcdir@/README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@ $(DESTDIR)$(prefix)/lib/jim
-       mkdir -p $(DESTDIR)$(prefix)/include
-       cp @srcdir@/jim.h @srcdir@/jim-eventloop.h @srcdir@/jim-nvp.h @srcdir@/jim-signal.h \
-               @srcdir@/jim-subcmd.h @srcdir@/jim-win32compat.h $(DESTDIR)$(prefix)/include
-       cp jim-config.h $(DESTDIR)$(prefix)/include
-       mkdir -p $(DESTDIR)$(prefix)/doc/jim
-       cp Tcl.html $(DESTDIR)$(prefix)/doc/jim
+install: all @TCL_EXTS@ install-exec install-docs
+       $(INSTALL_DATA_DIR) $(DESTDIR)@libdir@/jim
+       $(INSTALL_DATA) $(LIBJIM) $(DESTDIR)@libdir@
+       $(INSTALL_DATA) @srcdir@/README.extensions @C_EXT_SHOBJS@ $(DESTDIR)@libdir@/jim
+       for i in @TCL_EXTS@; do $(INSTALL_DATA) @srcdir@/$$i $(DESTDIR)@libdir@/jim; done
+       $(INSTALL_DATA_DIR) $(DESTDIR)@includedir@
+       $(INSTALL_DATA) @srcdir@/jim.h @srcdir@/jim-eventloop.h @srcdir@/jim-signal.h \
+               @srcdir@/jim-subcmd.h @srcdir@/jim-win32compat.h $(DESTDIR)@includedir@
+       $(INSTALL_DATA) jim-config.h $(DESTDIR)@includedir@
+       $(INSTALL_DATA_DIR) $(DESTDIR)@bindir@
+       $(INSTALL_DATA) build-jim-ext $(DESTDIR)@bindir@
 
 install-exec: all
-       mkdir -p $(DESTDIR)$(prefix)/bin
-       cp $(JIMSH) $(DESTDIR)$(prefix)/bin
+       $(INSTALL_DATA_DIR) $(DESTDIR)@bindir@
+       $(INSTALL_PROGRAM) $(JIMSH) $(DESTDIR)@bindir@
 
 uninstall:
-       rm -f $(DESTDIR)$(prefix)/bin/$(JIMSH)
-       rm -f $(DESTDIR)$(prefix)/lib/$(LIBJIM)
-       for i in README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@; do rm -f $(DESTDIR)$(prefix)/lib/jim/$$i; done
-       rm -f $(DESTDIR)$(prefix)/include/jim*.h
-       rm -f $(DESTDIR)$(prefix)/doc/jim/Tcl.html
+       rm -f $(DESTDIR)@bindir@/$(JIMSH)
+       rm -f $(DESTDIR)@bindir@/build-jim-ext
+       rm -f $(DESTDIR)@libdir@/$(LIBJIM)
+       for i in README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@; do rm -f $(DESTDIR)@libdir@/jim/$$i; done
+       rm -f $(DESTDIR)@includedir@/jim*.h
+       rm -f $(DESTDIR)@datadir@/doc/jim/Tcl.html
 @else
-install install-exec uninstall:
+install install-exec: all
+uninstall:
 @endif
 
-test: $(JIMSH)
-       $(DEF_LD_PATH) $(MAKE) -C @srcdir@/tests jimsh=`pwd`/jimsh
+test check: $(JIMSH)
+       cd @srcdir@/tests; $(DEF_LD_PATH) $(MAKE) jimsh=@builddir@/jimsh
 
-$(OBJS): Makefile
+$(OBJS): Makefile $(wildcard *.h)
 
 @if JIM_UTF8
 # Generate the unicode case mapping
@@ -109,37 +133,37 @@ $(LIBJIM): $(OBJS)
        $(RANLIB) $@
 @else
 $(LIBJIM): $(OBJS)
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SH_LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SH_LDFLAGS) -o $@ $(OBJS) $(LDLIBS) $(LIBS)
 @endif
 
 # Note that $> $^ is for compatibility with both GNU make and BSD make
 readdir.so: jim-readdir.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-readdir.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-readdir.o $(SH_LIBJIM) 
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-readdir.o $(SH_LIBJIM)
 
 array.so: jim-array.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-array.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-array.o $(SH_LIBJIM) 
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-array.o $(SH_LIBJIM)
 
 clock.so: jim-clock.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-clock.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-clock.o $(SH_LIBJIM) 
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-clock.o $(SH_LIBJIM)
 
 file.so: jim-file.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-file.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-file.o $(SH_LIBJIM) 
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-file.o $(SH_LIBJIM)
 
 posix.so: jim-posix.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-posix.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-posix.o $(SH_LIBJIM) 
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-posix.o $(SH_LIBJIM)
 
 regexp.so: jim-regexp.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-regexp.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-regexp.o $(SH_LIBJIM) 
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-regexp.o $(SH_LIBJIM)
 
 syslog.so: jim-syslog.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-syslog.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-syslog.o $(SH_LIBJIM) 
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-syslog.o $(SH_LIBJIM)
 
 readline.so: jim-readline.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-readline.o $> $^
@@ -149,9 +173,9 @@ pack.so: jim-pack.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-pack.o $> $^
        $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-pack.o $(SH_LIBJIM) @LDLIBS_pack@
 
-sqlite.so: jim-sqlite.c
-       $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sqlite.o $> $^
-       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-sqlite.o $(SH_LIBJIM) @LDLIBS_sqlite@
+tclprefix.so: jim-tclprefix.c
+       $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-tclprefix.o $> $^
+       $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-tclprefix.o $(SH_LIBJIM) @LDLIBS_tclprefix@
 
 sqlite3.so: jim-sqlite3.c
        $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sqlite3.o $> $^
@@ -173,10 +197,10 @@ Tcl.html: jim_tcl.txt
        @tclsh@ @srcdir@/make-index $> $^ | asciidoc -o $@ -d manpage - || cp @srcdir@/Tcl_shipped.html Tcl.html
 
 clean:
-       rm -f *.o *.so lib*.a $(JIMSH) Tcl.html _*.c
+       rm -f *.o *.so *.dll *.exe lib*.a $(JIMSH) $(LIBJIM) Tcl.html _*.c
 
 distclean: clean
-       rm -f jimautoconf.h jim-config.h Makefile config.log autosetup/jimsh0.c autosetup/jimsh0@EXEEXT@
+       rm -f jimautoconf.h jim-config.h Makefile config.log autosetup/jimsh0@EXEEXT@ build-jim-ext
 
 ship: Tcl.html
        cp $< Tcl_shipped.html
@@ -194,5 +218,3 @@ distdir:
 
 reconfig:
        CC='@CC@' @AUTOREMAKE@
-
-lib: $(LIBJIM)
old mode 100644 (file)
new mode 100755 (executable)
index 8acacc4..8ce8086
@@ -145,7 +145,7 @@ under following license:
  *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> 
+ * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
  * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
  * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
  * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
@@ -154,18 +154,18 @@ under following license:
  * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
  * Copyright 2009 Zachary T Welch zw@superlucidity.net
  * Copyright 2009 David Brownell
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above
  *    copyright notice, this list of conditions and the following
  *    disclaimer in the documentation and/or other materials
  *    provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
@@ -178,7 +178,7 @@ under following license:
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
+ *
  * The views and conclusions contained in the software and documentation
  * are those of the authors and should not be interpreted as representing
  * official policies, either expressed or implied, of the Jim Tcl Project.
diff --git a/jim/README.extensions b/jim/README.extensions
new file mode 100755 (executable)
index 0000000..0eaca1c
--- /dev/null
@@ -0,0 +1,15 @@
+The /lib/jim directory contains both dynamically loadable extensions
+and pure-Tcl extensions.
+
+Dynamically loadable extensions must have a .so file extension
+Tcl extensions must have a .tcl file extension
+
+As long as /lib/jim is in $::auto_path (it is by default), extension
+abc can be loaded with:
+
+  package require abc
+
+First abc.so will be tried, and then abc.tcl
+
+Note that this directory may be something like /lib/jim, /usr/lib/jim or
+/usr/local/lib/jim, depending upon where jim was installed.
diff --git a/jim/README.metakit b/jim/README.metakit
new file mode 100755 (executable)
index 0000000..ce9830b
--- /dev/null
@@ -0,0 +1,316 @@
+---
+title: Metakit
+---
+
+Metakit Extension for Jim Tcl
+=============================
+
+OVERVIEW
+--------
+The mk extension provides an interface to the Metakit small-footprint
+embeddable database library (<http://equi4.com/metakit/>). The underlying
+library is efficient at manipulating not-so-large amounts of data and takes a
+different approach to composing database operations than common SQL-based
+relational databases.
+
+Both the Metakit core library and the mk package can be linked either
+statically or dynamically and loaded using
+
+    package require mk
+
+CREATING A DATABASE
+-------------------
+A database (called a "storage" in Metakit terms) may either reside totally in
+memory or be backed by a file. To open or create a database, call the
+`storage` command with an optional filename parameter:
+
+    set db [storage test.mk]
+
+The returned handle can be used as a command name to access the database. When
+you are done, execute the `close` method, that is, run
+
+    $db close
+
+A lost handle won't be found by GC but will be closed when the interpreter
+exits. Note that by default Metakit will only record changes to the database
+when you close the handle. Use the `commit` method to record the current
+state of the database to disk.
+
+CREATING VIEWS
+--------------
+*Views* in Metakit are what is called "tables" in conventional databases. A view
+may several typed *properties*, or columns, and contains homogenous *rows*, or
+records. New properties may be added to a view as needed; however, new properties
+are not stored in the database file by default. The structure method specifies
+the stored properties of a view, creating a new view or restructuring an old one
+as needed:
+
+    $db structure viewName description
+
+The view description must be a list of form `{propName type propName type ...}`.
+The supported property types include:
+
+`string`
+:   A NULL-terminated string, stored as an array of bytes (without any encoding
+    assumptions).
+
+`binary`
+:   **Not yet supported by the `mk` extension.**
+    Blob of binary data that may contain embedded NULLs (zero bytes). Stored
+    as-is. This is more efficient than `string` when storing large blocks of
+    data (e.g. images) and will adjust the storage strategy as needed.
+
+`integer`
+:   An signed integer value occupying a maximum of 32 bits. If all values
+    stored in a column can fit in a smaller range (16, 8, or even 4 or 2 bits),
+    they are packed automatically.
+
+`long`
+:   Like `integer`, but is required to fit into 64 bits.
+
+`float` and `double`
+:   32-bit and 64-bit IEEE floating-point values respectively.
+
+`subview`
+:   This type is not usually specified directly; instead, a structure
+    description of a nested view is given. `subview` properties store complete
+    views as their value, creating hierarchical data structures. When retreived
+    from a view, a value of a subview property is a normal view handle.
+
+Without a `description` parameter, the `structure` method returns the current
+structure of the named view; without any parameters, it returns a dictionary
+containing structure descriptions of all views stored in the database.
+
+After specifying the properties you expect to see in the view, call
+
+    [$db view $viewName] as viewHandle
+
+to obtain a view handle. These handles are also commands, but are
+garbage-collected and also destroy themselves after a single method call; the
+`as viewHandle` call assigns the view handle to the specified variable and also
+tells the view not to destroy itself until all the references to it are gone.
+
+View handles may also be made permanent by giving them a global command name,
+e.g.
+
+    rename [$db view data] .db.data
+
+However, such view handles are not managed automatically at all and must be
+destroyed using the `destroy` method, or by renaming them to `""`.
+
+MANIPULATING DATA
+-----------------
+The value of a particular property is obtained using
+
+    cursor get $cur propName
+
+where `$cur` is a string of form `viewHandle!index`. Row indices are zero-based
+and may also be specified relative to the last row of the view using the
+`end[+-]integer` notation.
+
+A dictionary containing all property name and value pairs can be retreived by
+omitting the `propName` argument:
+
+    cursor get $cur
+
+Setting property values is also performed either individually, using
+
+    cursor set $cur propName value ?propName value ...?
+
+or via a dictionary with
+
+    cursor set $cur dictValue
+
+In the first form of the command, property names may also be preceded by a
+-_typeName_ option. In this case, a new property of the specified type will be
+created if it doesn't already exist; note that this will cause *all* the rows
+in the view to have the property (but see **A NOTE ON NULL** below).
+
+If the row index points after the end of the view, an appropriate number of
+fresh rows will be inserted first. So, for example, you can use `end+1`
+to append a new row. (Note that you then have to set it all at once, though.)
+
+The total number of rows can be obtained using
+
+    $viewHandle size
+
+and set manually with
+
+    $viewHandle resize newSize
+
+For example, you can use `$viewHandle resize 0` to clear a view.
+
+INSERT AND REMOVE
+-----------------
+New rows may also be inserted at an arbitrary position in a view with
+
+    cursor insert $cur ?count?
+
+This will insert _count_ fresh rows into the view so that _$cur_ points to
+the first one. The inverse of this operation is
+
+    cursor remove $cur ?count?
+
+COMPOSING VIEWS
+---------------
+The real power of Metakit lies in the way existing views are combined to create
+new ones to obtain a particular perspective on the stored data. A single
+operation takes one or more views and possibly additional options and produces a
+new view, usually tracking notifications to the underlying views and sometimes
+even supporting modification.
+
+Binary operations are left-biased when there are conflicting property values;
+that is, they always prefer the values from the left view.
+
+### Unary operations ###
+
+*view* `unique`
+:   Derived view with duplicate rows removed.
+
+*view* `sort` *crit ?crit ...?*
+:   Derived view sorted on the specified criteria, in order. A single _crit_
+    is either a property name or a property name preceded by a dash; the latter
+    specifies that the sorting is to be performed in reverse order.
+
+### Binary operations ###
+
+The operations taking _set_ arguments require that the given views have no
+duplicate rows. The `unique` method can be used to ensure this.
+
+*view1* `concat` *view2*
+:   Vertical concatenation; that is, all the rows of _view1_ and then all rows
+    of _view2_.
+
+*view1* `pair` *view2*
+:   Pairing, or horizontal concatenation: every row in _view1_ is matched with
+    a row with the same index in _view2_; the result has all the properties of
+    _view1_ and all the properties of _view2_.
+
+*view1* `product` *view2*
+:   Cartesian product: each row in _view1_ horizontally concatenated with every
+    row in _view2_.
+
+*set1* `union` *set2*
+:   Set union. Unlike `concat`, this operation removes duplicates from the
+    result. A row is in the result if it is in _set1_ **or** in _set2_.
+
+*set1* `intersect` *set2*
+:   Set intersection. A row is in the result if it is in _set1_ **and** in
+    _set2_.
+
+*set1* `different` *set2*
+:   Symmetric difference. A row is in the result if it is in _set1_ **xor** in
+    _set2_, that is, in _set1_ or in _set2_, but not in both.
+
+*set1* `minus` *set2*
+:   Set minus. A row is in the result if it is in _set1_ **and not** in _set2_.
+
+### Relational operations ###
+
+*view1* `join` *view2* ?`-outer`? *prop ?prop ...?*
+:   Relational join on the specified properties: the rows from _view1_ and
+    _view2_ with all the specified properties equal are concatenated to form a
+    new row. If the `-outer` option is specified, the rows from _view1_ that do
+    not have a corresponding one in _view2_ are also left in the view, with the
+    properties existing only in _view2_ filled with default values.
+
+*view* `group` *subviewName prop ?prop ...?*
+:   Groups the rows with all the specified properties equal; moves all the
+    remaining properties into a newly created subview property called
+    _subviewName_.
+
+*view* `flatten` *subviewProp*
+:   The inverse of `group`.
+
+### Projections and selections ###
+
+*view* `project` *prop ?prop ...?*
+:   Projection: a derived view with only the specified properties left.
+
+*view* `without` *prop ?prop ...?*
+:   The opposite of `project`: a derived view with the specified properties
+    removed.
+
+*view* `range` *start end ?step?*
+    A slice or a segment of _view_: rows at _start_, _start+step_, and so on,
+    until the row number becomes larger than _end_. The usual `end[+-]integer`
+    notation is supported, but the indices don't change if the underlying view
+    is resized.
+
+**(!) select etc. should go here**
+
+### Search and storage optimization ###
+
+*view* `blocked`
+:   Invokes an optimization designed for storing large amounts of data. _view_
+    must have a single subview property called `_B` with the desired structure
+    inside. This additional level of indirection is used by `blocked` to create
+    a view that looks like a usual one, but can store much more data
+    efficiently. As a result, indexing into the view becomes a bit slower. Once
+    this method is invoked, all access to _view_ must go through the returned
+    view.
+
+*view* `ordered` *prop ?prop ...?*
+:   Does not transform the structure of the view in any way, but signals that
+    the view should be considered ordered on a unique key consisting of the
+    specified properties, enabling some optimizations. Note that duplicate keys
+    are not allowed in an ordered view.
+
+**(!) TODO: hash, indexed(?) -- these make no sense until searches are implemented**
+
+### Pipelines ###
+
+Because constructs like `[[view op1 ...] op2 ...] op3 ...` tend to be common in
+programs using Metakit, a shorthand syntax is introduced: such expressions may
+also be written as `view op1 ... | op2 ... | op3 ...`.
+
+Note though that this syntax is not in any way magically wired into the
+interpreter: it is understood only by the view handles and the two commands that
+can possibly return a view: `$db view` and `cursor get`. If you want to support
+this syntax in Tcl procedures, you'll need to do this yourself, or you may want
+to create a custom view method and have the view handle work out the syntax for
+you (see **USER-DEFINED METHODS** below).
+
+OTHER VIEW METHODS
+------------------
+
+*view* `copy`
+:   Creates a copy of view with the same data.
+
+*view* `clone`
+:   Creates a view with the same structure, but no data.
+
+*view* `pin`
+:   Specifies that the view should not be destroyed after a single method call.
+    Returns _view_.
+
+*view* `as` *varName*
+:   In addition to the actions performed by `pin`, assigns the view handle to
+    the variable named varName in the caller's scope.
+
+*view* `properties`
+:   Returns the names of all properties in the view.
+
+*view* `type` *prop*
+:   Returns the type of the specified property.
+
+A NOTE ON NULL
+--------------
+Note that Metakit does not have a special `NULL` value like conventional
+relational databases do. Instead, it defines _default_ property values: `""` for
+`string` and `binary` types, `0` for all numeric types and a view with no rows
+for subviews. These defaults are used when a fresh row is inserted and when
+a new property is added to the view to fill in the missing values.
+
+USER-DEFINED METHODS
+--------------------
+The storage and view handles support custom methods defined in Tcl: to define
+_methodName_ on every storage or view handle, create a procedure called
+{`mk.storage` *methodName*} or {`mk.view` *methodName*} respectively. These
+procedures will receive the handle as the first argument and all the remaining
+arguments. Remember to `pin` the view handle in view methods if you call more
+than one method of it!
+
+Custom `cursor` subcommands may also be defined by creating a procedure called
+{`cursor` *methodName*}. These receive all the arguments without any
+modifications.
diff --git a/jim/README.namespaces b/jim/README.namespaces
new file mode 100755 (executable)
index 0000000..e08d68e
--- /dev/null
@@ -0,0 +1,191 @@
+Lightweight Namespaces for Jim Tcl
+==================================
+
+There are two broad requirements for namespace support in Jim Tcl.
+
+1. To allow code from multiple sources while reducing the chance of name clashes
+2. To simplify porting existing Tcl code which uses namespaces
+
+This proposal addresses both of these requirements, with the following
+additional requirements imposed by Jim Tcl.
+
+3. Support for namespaces should be optional, with the space and time overhead
+   when namespaces are disabled as close to zero as possible.
+4. The implementation should be small and reasonably efficient.
+
+To further expand on requirement (2), the goal is not to be able to run
+any Tcl scripts using namespaces with no changes. Rather, scripts
+which use namespaces in a straightforward manner, should be easily
+ported with changes which are compatible with Tcl.
+
+Implicit namespaces
+-------------------
+Rather than supporting explicit namespaces as Tcl does, Jim Tcl
+supports implicit namespaces. Any procedure or variable which
+is defined with a name containing ::, is implicitly scoped within
+a namespace.
+
+For example, the following procedure and variable are created
+in the namespace 'test'
+
+proc ::test::myproc {} {
+  puts "I am in namespace [namespace current]"
+}
+set ::test::myvar 3
+
+This approach allows much of the existing variable and command
+resolution machinery to be used with little change. It also means
+that it is possible to simply define a namespace-scoped variable
+or procedure without first creating the namespace, and similarly,
+namespaces "disappear" when all variables and procedures defined
+with the namespace scope are deleted.
+
+Namespaces, procedures and call frames
+--------------------------------------
+When namespace support is enabled (at build time), each procedure has an associated
+namespace (based on the procedure name). When the procedure is evaluated,
+the namespace for the created call frame is set to the namespace associated
+with the procedure.
+
+Command resolution is based on the namespace of the current call frame.
+An unscoped command name will first be looked up in the current namespace,
+and then in the global namespace.
+
+This also means that commands which do not create a call frame (such as commands
+implemented in C) do not have an associated namespace.
+
+Similarly to Tcl, namespace eval introduces a temporary, anonymous
+call frame with the associated namespace. For example, the following
+will return "::test,1".
+
+namespace eval test {
+       puts [namespace current],[info level]
+}
+
+Variable resolution
+-------------------
+The variable command in Jim Tcl has the same syntax as Tcl, but is closer in behaviour to the global command.
+The variable command creates a link from a local variable to a namespace variable, possibly initialising it.
+
+For example, the following procedure uses 'variable' to initialse and access myvar.
+
+proc ::test::myproc {} {
+  variable myvar 4
+  incr myvar
+}
+
+Note that there is no automatic resolution of namespace variables.
+For example, the following will *not* work.
+
+namespace eval ::test {
+  variable myvar 4
+}
+namespace eval ::test {
+  # This will increment a local variable, not ::test::myvar
+  incr myvar
+}
+
+And similarly, the following will only access local variables
+
+set x 3
+namespace eval ::test {
+       # This will incremement a local variable, not ::x
+       incr x
+       # This will also increment a local variable
+       incr abc::def
+}
+
+In the same way that variable resolution does not "fall back" to
+global variables, it also does not "fall back" to namespace variables.
+
+This approach allows name resolution to be simpler and more efficient
+since it uses the same variable linking mechanism as upvar/global
+and it allows namespaces to be implicit. It also solves the "creative
+writing" problem where a variable may be created in an unintentional
+scope.
+
+The namespace command
+---------------------
+Currently, the following namespace commands are supported.
+
+* current - returns the current, fully-qualified namespace
+* eval - evaluates a script in a namespace (introduces a call frame)
+* qualifiers, tail, parent - note that these do not check for existence
+* code, inscope - implemented
+* delete - deletes all variables and commands with the namespace prefix
+* which - implemented
+* upvar - implemented
+
+namespace children, exists, path
+--------------------------------
+With implicit namespaces, the namespace exists and namespace children commands
+are expensive to implement and are of limited use. Checking the existence
+of a namespace can be better done by checking for the existence of a known procedure
+or variable in the namespace.
+
+Command resolution is always done by first looking in the namespace and then
+at the global scope, so namespace path is not required.
+
+namespace ensemble
+------------------
+The namespace ensemble command is not currently supported. A future version
+of Jim Tcl will have a general-purpose ensemble creation and manipulation
+mechanism and namespace ensemble will be implemented in terms of that mechanism.
+
+namespace import, export, forget, origin
+----------------------------------------
+Since Jim Tcl namespaces are implicit, there is no location to store export patterns.
+Therefore the namespace export command is a dummy command which does nothing.
+All procedures in a namespace are considered to be exported.
+
+The namespace import command works by creating aliases to the target namespace
+procedures.
+
+namespace forget is not implemented.
+
+namespace origin understands aliases created by namespace import
+and can return the original command.
+
+namespace unknown
+-----------------
+If an undefined command is invoked, the "unknown" command is invoked.
+The same namespace resolution rules apply for the unknown command.
+This means that in the following example, test::unknown will be invoked
+for the missing command rather than the global ::unknown.
+
+proc unknown {args} {
+       puts "global unknown"
+}
+
+proc test::unknown {args} {
+       puts "test unknown"
+}
+
+namespace eval test {
+       bogus
+}
+
+This approach requires no special support and provides enough flexibility that
+the namespace unknown command is not implemented.
+
+Porting namespace code from Tcl to Jim Tcl
+------------------------------------------
+For most code, the following changes will be sufficient to port code.
+
+1. Canonicalise namespace names. For example, ::ns:: should be written
+   as ::ns or ns as appropriate, and excess colons should be removed.
+   For example ::ns:::blah should be written as ::ns::blah
+   (Note that the only "excess colon" case supported is ::::abc
+   in order to support [namespace current]::abc in the global namespace)
+
+2. The variable command should be used within namespace eval to link
+   to namespace variables, and access to variables in other namespaces
+   should be fully qualified
+
+Changes in the core Jim Tcl
+---------------------------
+Previously Jim Tcl performed no scoping of command names.  i.e. The
+::format command was considered different from the format command.
+
+Even if namespace support is disabled, the command resolution will
+recognised global scoping of commands and treat these as identical.
diff --git a/jim/README.oo b/jim/README.oo
new file mode 100755 (executable)
index 0000000..fc59faf
--- /dev/null
@@ -0,0 +1,253 @@
+OO Package for Jim Tcl
+======================
+
+Author: Steve Bennett <steveb@workware.net.au>
+Date: 1 Nov 2010 09:18:40
+
+OVERVIEW
+--------
+The pure-Tcl oo package leverages Jim's unique strengths
+to provide support for Object Oriented programming.
+
+The oo package can be statically linked with Jim or installed
+as a separate Tcl package and loaded with:
+
+  package require oo
+
+DECLARING CLASSES
+-----------------
+A class is declared with the 'class' proc as follows.
+
+  class myclass ?baseclasses? classvars
+
+This declares a class named 'myclass' with the given dictionary,
+'classvars', providing the initial state of all new objects.
+It is important to list all class variables in 'classvars', even
+if initialised only to the empty string, since the class makes
+these variables available in methods and via [myclass vars].
+
+A list of zero or more base classes may also be specified from
+which methods and class variables are imported. See INHERITANCE
+below for more details.
+
+Declaring a class creates a procedure with the class name along
+with some related procedures. For example:
+
+  . class Account {balance 0}
+  Account
+  . info procs Account*
+  {Account get} {Account methods} {Account eval} Account {Account new} {Account destroy}
+  {Account vars} {Account classname} {Account classvars} {Account method}
+
+Notice that apart from the main 'Account' procedure, all the remaining procedures (methods)
+are prefixed with 'Account' and a space.
+
+PREDEFINED CLASS METHODS
+------------------------
+Decaring a class pre-defines a number of "class" methods. i.e. those which don't
+require an object and simply return or manipulate properties of the class. These are:
+
+  new ?instancevars?::
+    Creates and returns new object, optionally overriding the default class variable values.
+       Note that the class name is an alias for 'classname new {}' and can be used as a shorthand
+       for creating new objects with default values.
+
+  method name arglist body::
+    Creates or redefines a method for the class with the given name, argument list and body.
+
+  methods::
+    Returns a list of the methods supported by this class, including both class methods
+       and instance methods. Also includes base class methods.
+
+  vars::
+       Returns a list of the class variables for this class (names
+       only). Also includes base class variables.
+
+  classvars::
+       Returns a dictionary the class variables, including initial values, for this class.
+       Also includes base class variables.
+
+  classname::
+    Returns the classname. This can be useful as [$self classname].
+
+Class methods may be invoked either via the class name or via an object of the class.
+For example:
+
+  . class Account {balance 0}
+  Account
+  . Account methods
+  classname classvars destroy eval get method methods new vars
+  . set a [Account]
+  <reference.<Account>.00000000000000000001>
+  . $a methods
+  classname classvars destroy eval get method methods new vars
+
+PREDEFINED OBJECT METHODS
+-------------------------
+Decaring a class pre-defines a number of "object" methods. i.e. those which operate
+on a specific object.
+
+  destroy::
+    Destroys the object. This method may be overridden, but note that it should
+       delete the object with {rename $self ""}. This method will also be called
+       if the object is reaped during garbage collection.
+
+  get varname::
+    Returns the value of the given instance variable.
+
+  eval ?locals? body::
+    Makes any given local variables available to the body, along with
+       the instance variables, and evaluate the body in that context.
+       This can be used for one-off evaluation to avoid declaring a method.
+
+CREATING OBJECTS
+----------------
+An object is created with the 'new' method, or simply by using the classname shortcut.
+If the 'new' method is used, the variables for the newly created object (instance variables)
+may be initialised. Otherwise they are set to the default values specified when the
+class was declared.
+
+For example:
+
+  . class Account {balance 0}
+  Account
+  . set a [Account]
+  <reference.<Account>.00000000000000000001>
+  . set b [Account new {balance 1000}]
+  <reference.<Account>.00000000000000000002>
+  . $a get balance
+  0
+  . $b get balance
+  1000
+
+DECLARING METHODS
+-----------------
+In addition to the predefined methods, new methods may be decared, or existing
+methods redefined with the class method, method.
+
+Declaring a method is very similar to defining a proc, and the arglist
+has identical syntax. For example:
+
+  . Account method show {{channel stdout}} { $channel puts "Balance of account is $balance" }
+  . $b show
+  Balance of account is 1000
+
+All instance variables are available within the method and any
+changes to these variables are maintained by the object.
+
+In addition, the $self variables is defined and refers to the current object.
+This may be used to invoke further methods on the object. For example:
+
+  . Account method show {} { puts "Balance of account is [$self get balance]" }
+  . $b show
+  Balance of account is 1000
+
+Notes:
+* It is a bad idea to unset an instance variable.
+* In general, you should avoid redefining any of the pre-defined methods, except for 'destroy'.
+* When accessing the caller's scope with upvar or uplevel, note that there
+  are two frame levels between the caller and the method. Thus it is necessary
+  to use 'upvar 2' or 'uplevel 2'
+
+INHERITANCE
+-----------
+For each base class given in a new class declaration, the methods
+and variables of those classes are imported into the new class being
+defined. Base classes are imported in left to right order, so that if a
+method is defined in more than one base class, the later definition
+is selected. This applies similarly to class variables.
+
+Within a method, 'super' may be used to explicitly invoke a
+base class method on the object. This applies only to the *last*
+base class given. For example:
+
+  # Assumes the existence of classes Account and Client
+  . Account method debit {amount} { incr balance -$amount }
+  . class CreditAccount {Client Account} {type visa}
+  CreditAccount
+  . CreditAccount method debit {amount} {
+    puts "Debit $type card"
+       super debit $amount
+  }
+  . set a [CreditAccount]
+  <reference.<Account>.00000000000000000001>
+  . $a debit 20
+  Debit visa card
+  . $a balance
+  -20
+
+In the CreditAccount debit method, the call to 'super debit' invokes
+the method 'Account debit' since Account is the last base class listed.
+
+OBJECT LIFETIME/GARBAGE COLLECTION
+----------------------------------
+Objects are implemented as lambdas. That is, they are procedures with state
+and are named as references. This means that when an object is no longer
+reachable by any name and garbage collection runs, the object will be
+discarded and the destructor will be invoked. Note that the garbage collector
+can be invoked manually with 'collect' if required.
+
+  . class Account {}
+  Account
+  . Account method destroy {} { puts dying...; rename $self "" }
+  Account destroy
+  . proc a {} { set b [Account]; return "" }
+  a
+  . a
+  . collect
+  dying...
+  1
+
+CLASS METHODS/CLASS STATIC VARIABLES
+------------------------------------
+All methods defined with 'method' operate on objects (instances).
+If a class method is required, it is possible to simply declare one with 'proc'.
+The method dispatcher will automatically be able to dispatch to this method.
+Using this approach, it is also possible to add class static variables by
+defining static variables to the proc. Although strictly these variables
+are accessible only to that proc, not the class as a whole.
+
+For example:
+
+  . class Account {}
+  Account
+  . proc {Account nextid} {} {{id 0}} { incr id }
+  Account nextid
+  . Account nextid
+  1
+  . Account nextid
+  2
+  . set a [Account]
+  <reference.<Account>.00000000000000000001>
+  . $a nextid
+  3
+  . $a eval { $self nextid }
+  4
+
+HOW METHOD DISPATCH WORKS
+-------------------------
+All class and object methods are name "classname methodname".
+
+The class method dispatcher is named "classname". When invoked with a methodname,
+it simply invokes the method "classname methodname".
+
+The method dispatch is via a two step process. Firstly the object procedure is invoked
+with the method name. This procedure then invokes "classname method" which sets up
+the appropriate access to the object variables, and then invokes the method body.
+
+EXAMPLES
+--------
+tree.tcl
+~~~~~~~~
+The 'tree' package is implemented using the 'oo' package.
+See the source code in tree.tcl and a usage example in tests/tree.test
+
+Of particular note is how callbacks and recursive invocation is used in the 'walk' method.
+
+examples/ootest.tcl
+~~~~~~~~~~~~~~~~~~~
+A comprehensive OO example is provided in examples/ootest.tcl.
+
+It can be run simply as:
+
+  ./jimsh examples/ootest.tcl
diff --git a/jim/README.sqlite b/jim/README.sqlite
new file mode 100755 (executable)
index 0000000..dde7de5
--- /dev/null
@@ -0,0 +1,177 @@
+Jim Sqlite extension documentation.
+Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
+
+
+Overview
+~~~~~~~~
+
+The Sqlite extension makes possible to work with sqlite (http://www.sqlite.org)
+databases from Jim. SQLite is a small C library that implements a
+self-contained, embeddable, zero-configuration SQL database engine. This
+means it is perfect for embedded systems, and for stand-alone applications
+that need the power of SQL without to use an external server like Mysql.
+
+Basic usage
+~~~~~~~~~~~
+
+The Sqlite extension exports an Object Based interface for databases. In order
+to open a database use:
+
+  set f [sqlite3.open dbname]
+
+The [sqlite3.open] command returns a db handle, that is a command name that
+can be used to perform operations on the database. A real example:
+
+    . set db [sqlite3.open test.db]
+    sqlite.handle0
+    . $db query "SELECT * from tbl1"
+    {one hello! two 10} {one goodbye two 20}
+
+In the second line the handle is used as a command name, followed
+by the 'method' or 'subcommand' ("query" in the example), and the arguments.
+
+The query method
+~~~~~~~~~~~~~~~~
+
+The query method has the following signature:
+
+    $db query SqlQuery ?args?
+
+The sql query may contain occurrences of "%s" that are substituted
+in the actual query with the following arguments, quoted in order
+to make sure that the query is correct even if this arguments contain
+"'" characters. So for example it is possible to write:
+
+    . $db query "SELECT * from tbl1 WHERE one='%s'" hello!
+    {one hello! two 10}
+
+Instead of hello! it is possible to use a string with embedded "'":
+
+    . $db query "SELECT * from tbl1 WHERE one='%s'" a'b
+    (no matches - the empty list is returned)
+
+This does not work instead using the Tcl variable expansion in the string:
+
+    . $db query "SELECT * from tbl1 WHERE one='$foo'"
+    Runtime error, file "?", line 1:
+        near "b": syntax error
+
+In order to obtain an actual '%' character in the query, there is just
+to use two, like in "foo %% bar". This is the same as the [format] argument.
+
+Specification of query results
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In one of the above examples, the following query was used:
+
+    . $db query "SELECT * from tbl1"
+    {one hello! two 10} {one goodbye two 20}
+
+As you can see the result of a query is a list of lists. Every
+element of the list represents a row, as a list of key/value pairs,
+so actually every row is a Jim dictionary.
+
+The following example and generated output show how to take advantage
+of this representation:
+
+    . set res [$db query "SELECT * from tbl1"]
+    {one hello! two 10} {one goodbye two 20}
+    . foreach row $res {puts "One: $row(one), Two: $row(two)"}
+    One: hello!, Two: 10
+    One: goodbye, Two: 20
+
+To access every row sequentially is very simple, and field of a row
+can be accessed using the $row(field) syntax.
+
+The close method
+~~~~~~~~~~~~~~~~
+
+In order to close the db, use the 'close' method that will have as side effect
+to close the db and to remove the command associated with the db.
+Just use:
+
+    $db close
+
+Handling NULL values
+~~~~~~~~~~~~~~~~~~~~
+
+In the SQL language there is a special value NULL that is not the empty
+string, so how to represent it in a typeless language like Tcl?
+For default this extension will use the empty string, but it is possible
+to specify a different string for the NULL value.
+
+In the above example there were two rows in the 'tbl1' table. Now
+we can add using the "sqlite" command line client another one with
+a NULL value:
+
+    sqlite> INSERT INTO tbl1 VALUES(NULL,30);
+    sqlite> .exit
+
+That's what the sqlite extension will return for default:
+
+    . $db query "SELECT * from tbl1"
+    {one hello! two 10} {one goodbye two 20} {one {} two 30}
+
+As you can see in the last row, the NULL is represented as {}, that's
+the empty string. Using the -null option of the 'query' command we
+can change this default, and tell the sqlite extension to represent
+the NULL value as a different string:
+
+    . $db query -null <<NULL>> "SELECT * from tbl1"
+    {one hello! two 10} {one goodbye two 20} {one <<NULL>> two 30}
+
+This way if the emtpy string has some semantical value for your
+dataset you can change it.
+
+Finding the ID of the last inserted row
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is as simple as:
+
+    . $db lastid
+    10
+
+Number of rows changed by the most recent query
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is also very simple, there is just to use the 'changes' method
+without arugments.
+
+    . $db changes
+    5
+
+Note that if you drop an entire table the number of changes will
+be reported as zero, because of details of the sqlite implementation.
+
+That's all,
+Enjoy!
+Salvatore Sanfilippo
+
+p.s. this extension is just the work of some hour thanks to the cool
+clean C API that sqlite exports. Thanks to the author of sqlite for this
+great work.
+
+In memory databases
+~~~~~~~~~~~~~~~~~~~
+
+SQLite is able to create in-memory databases instead to use files.
+This is of course faster and does not need the ability to write
+to the filesystem. Of course this databases are only useful for
+temp data.
+
+In-memory DBs are used just like regular databases, just the name used to
+open the database is :memory:. That's an example that does not use the
+filesystem at all to create and work with the db.
+
+  package require sqlite3
+  set db [sqlite3.open :memory:]
+  $db query {CREATE TABLE plays (id, author, title)}
+  $db query {INSERT INTO plays (id, author, title) VALUES (1, 'Goethe', 'Faust');}
+  $db query {INSERT INTO plays (id, author, title) VALUES (2, 'Shakespeare', 'Hamlet');}
+  $db query {INSERT INTO plays (id, author, title) VALUES (3, 'Sophocles', 'Oedipus Rex');}
+  set res [$db query "SELECT * FROM plays"]
+  $db close
+  foreach r $res {puts $r(author)}
+
+Of course once the Jim process is destroyed the database will no longer
+exists.
diff --git a/jim/README.usb_modeswitch b/jim/README.usb_modeswitch
deleted file mode 100644 (file)
index 7f3ae41..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-The content of this folder is customized for shipping with usb_modeswitch;
-for the original source see:
-
-http://repo.or.cz/w/jimtcl.git
-
-This is version 0.72 of jimtcl
diff --git a/jim/README.utf-8 b/jim/README.utf-8
new file mode 100755 (executable)
index 0000000..7128d76
--- /dev/null
@@ -0,0 +1,123 @@
+UTF-8 Support for Jim Tcl
+=========================
+
+Author: Steve Bennett <steveb@workware.net.au>
+Date: 2 Nov 2010 10:55:52 EST
+
+OVERVIEW
+--------
+Traditionally Jim Tcl has support strings, including binary strings containing
+nulls, however it has had no support for multi-byte character encodings.
+
+In some fields, such as when dealing with the web, or other user-generated content,
+support for multi-byte character encodings is necessary.
+In these cases it would be very useful for Jim Tcl to be able to process strings
+as multi-byte character strings rather than simply binary bytes.
+
+Supporting multiple character encodings and translation between those encodings
+is beyond the scope of Jim Tcl. Therefore, Jim has been enhanced to add support
+for UTF-8, as probably the most popular general purpose multi-byte encoding.
+
+UTF-8 support is optional. It can be enabled at compile time with:
+
+  ./configure --enable-utf8
+
+The Jim Tcl documentation fully documents the UTF-8 support. This README includes
+additional background information.
+
+Unicode vs UTF-8
+----------------
+It is important to understand that Unicode is an abstract representation
+of the concept of a "character", while UTF-8 is an encoding of
+Unicode into bytes.  Thus the Unicode codepoint U+00B5 is encoded
+in UTF-8 with the byte sequence: 0xc2, 0xb5. This is different from
+ASCII which the same name is used interchangeably between a character
+set and an encoding.
+
+Unicode Escapes
+---------------
+Even without UTF-8 enabled, it is useful to be able to encode UTF-8 characters
+in strings. This can be done with the \uNNNN Unicode escape. This syntax
+is compatible with Tcl and is enabled even if UTF-8 is disabled.
+
+Like Tcl, currently only 16-bit Unicode characters can be encoded.
+
+UTF-8 Properties
+----------------
+Due to the design of the UTF-8 encoding, many (most) commands continue
+to work with UTF-8 strings. This is due to the following properties of UTF-8:
+
+* ASCII characters in strings have the same representation in UTF-8
+* An ASCII string will never match the middle of a multi-byte UTF-8 sequence
+* UTF-8 strings can be sorted as bytes and produce the same result as sorting
+  by characters
+* UTF-8 strings in Jim continue to be null terminated
+
+Commands Supporting UTF-8
+-------------------------
+The following commands have been enhanced to support UTF-8 strings.
+
+* array {get,names,unset}
+* case
+* glob
+* lsearch -glob, -regexp
+* switch -glob, -regexp
+* regexp, regsub
+* format
+* scan
+* split
+* string index, range, length, compare, equal, first, last, map, match, reverse, tolower, toupper
+* string bytelength (new)
+* info procs, commands, vars, globals, locals
+
+Character Classes
+-----------------
+Jim Tcl has no support for UTF-8 character classes.  Thus [:alpha:]
+will match [a-zA-Z], but not non-ASCII alphabetic characters.  The
+same is true for 'string is'.
+
+Regular Expressions
+-------------------
+Normally, Jim Tcl uses the system-supplied POSIX-compatible regex
+implementation.
+
+Typically systems do not provide a UTF-8 capable regex implementation,
+therefore when UTF-8 support is enabled, the built-in regex
+implementation is used which includes UTF-8 support.
+
+Case Insensitivity
+------------------
+Case folding is much more complex under Unicode than under ASCII.
+For example it is possible for a character to change the number of
+bytes required for representation when converting from one case to
+another. Jim Tcl supports only "simple" case folding, where case
+is folded only where the number of bytes does not change.
+
+Case folding tables are automatically generated from the official
+unicode data table at http://unicode.org/Public/UNIDATA/UnicodeData.txt
+
+Working with Binary Data and non-UTF-8 encodings
+------------------------------------------------
+Almost all Jim commands will work identically with binary data and
+UTF-8 encoded data, including read, gets, puts and 'string eq'.  It
+is only certain string manipulation commands which will operated
+differently.  For example, 'string index' will return UTF-8 characters,
+not bytes.
+
+If it is necessary to manipulate strings containing binary, non-ASCII
+data (bytes >= 0x80), there are two options.
+
+1. Build Jim without UTF-8 support
+2. Arrange to encode and decode binary data or data in other encodings
+   to UTF-8 before manipulation.
+
+Internal Details
+----------------
+Jim_Utf8Length() will calculate the character length of the string and cache
+it for later access. It uses utf8_strlen() which relies on the string to be null
+terminated (which it always will be).
+
+It is possible to tell if a string is ascii-only because length == bytelength
+
+It is possible to provide optimised versions of various routines for
+the ascii-only case. Currently this is done only for 'string index' and 'string range'.
diff --git a/jim/STYLE b/jim/STYLE
new file mode 100755 (executable)
index 0000000..7a9b56c
--- /dev/null
+++ b/jim/STYLE
@@ -0,0 +1,64 @@
+This file summarizes the C style used for Jim.
+Copyright (C) 2005 Salvatore Sanfilippo.
+
+-----------
+INDENTATION
+-----------
+
+Indentation is 4 spaces, no smart-tabs are used (i.e.
+two indentation steps of 4 spaces will not be converted
+into a real tab, but 8 spaces).
+
+---------------
+FUNCTIONS NAMES
+---------------
+
+Functions names of exported functions are in the form:
+
+Jim_ExportedFunctionName()
+
+The prefix is "Jim_", every word composing the function name
+is capitalized.
+
+Not exported functions that are of general interest for the Jim
+core, like JimFreeInterp() are capitalized the same way, but the
+prefix used for this functions is "Jim" instead of "Jim_".
+Another example is:
+
+JimNotExportedFunction()
+
+Not exported functions that are not general, like functions
+implementing hashtables or Jim objects methods can be named
+in any prefix as long as capitalization rules are followed,
+like in:
+
+ListSetIndex()
+
+---------------
+VARIABLES NAMES
+---------------
+
+Global variables follow the same names convention of functions.
+
+Local variables have usually short names. A counter is just 'i', or 'j',
+or something like this. When a longer name is required, composed of
+more words, capitalization is used, but the first word starts in
+lowcase:
+
+thisIsALogVarName
+
+----
+GOTO
+----
+
+Goto is allowed every time it makes the code cleaner, like in complex
+functions that need to handle exceptions, there is often an "err" label
+at the end of the function where allocated resources are freed before to exit
+with an error. Goto is also used in order to escape multiple nested loops.
+
+----------
+C FEATURES
+----------
+
+Only C89 ANSI C is allowed. C99 features can't be used currently.
+GCC extensions are not allowed.
diff --git a/jim/TODO b/jim/TODO
new file mode 100755 (executable)
index 0000000..fc62aef
--- /dev/null
+++ b/jim/TODO
@@ -0,0 +1,26 @@
+CORE LANGUAGE FEATURES
+
+CORE COMMANDS
+
+- [onleave] command, executing something as soon as the current procedure
+  returns. With no arguments it returns the script set, with one appends
+  the onleave script. There should be a way to reset.
+
+  Currently we have [local] which can be used to delete procs on proc exit.
+  Also try/on/finally. Is [onleave] really needed?
+
+OTHER COMMANDS NOT IN TCL BUT THAT SHOULD BE IN JIM
+
+- Set commands: [lunion], [lintersect], and [ldifference]
+
+EXTENSIONS
+
+- Cryptography: hash functions, block ciphers, strim ciphers, PRNGs.
+- Tuplespace extension (http://wiki.tcl.tk/3947) (using sqlite as backend)
+- Zlib
+- Gdlib
+- CGI (interface compatible with ncgi, but possibly written in C for speed)
+
+REFERENCES SYSTEM
+
+- Unify ref/getref/setref/collect/finalize under an unique [ref] command.
diff --git a/jim/Tcl_shipped.html b/jim/Tcl_shipped.html
new file mode 100755 (executable)
index 0000000..9303491
--- /dev/null
@@ -0,0 +1,8170 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.6.6" />
+<title>Jim Tcl(n)</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+  font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+  font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+  margin: 1em 5% 1em 5%;
+}
+
+a {
+  color: blue;
+  text-decoration: underline;
+}
+a:visited {
+  color: fuchsia;
+}
+
+em {
+  font-style: italic;
+  color: navy;
+}
+
+strong {
+  font-weight: bold;
+  color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: #527bbd;
+  margin-top: 1.2em;
+  margin-bottom: 0.5em;
+  line-height: 1.3;
+}
+
+h1, h2, h3 {
+  border-bottom: 2px solid silver;
+}
+h2 {
+  padding-top: 0.5em;
+}
+h3 {
+  float: left;
+}
+h3 + * {
+  clear: left;
+}
+h5 {
+  font-size: 1.0em;
+}
+
+div.sectionbody {
+  margin-left: 0;
+}
+
+hr {
+  border: 1px solid silver;
+}
+
+p {
+  margin-top: 0.5em;
+  margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+  margin-top: 0;
+}
+ul > li     { color: #aaa; }
+ul > li > * { color: black; }
+
+pre {
+  padding: 0;
+  margin: 0;
+}
+
+#author {
+  color: #527bbd;
+  font-weight: bold;
+  font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+  font-size: small;
+  border-top: 2px solid silver;
+  padding-top: 0.5em;
+  margin-top: 4.0em;
+}
+#footer-text {
+  float: left;
+  padding-bottom: 0.5em;
+}
+#footer-badges {
+  float: right;
+  padding-bottom: 0.5em;
+}
+
+#preamble {
+  margin-top: 1.5em;
+  margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.admonitionblock {
+  margin-top: 2.0em;
+  margin-bottom: 2.0em;
+  margin-right: 10%;
+  color: #606060;
+}
+
+div.content { /* Block element content. */
+  padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+  color: #527bbd;
+  font-weight: bold;
+  text-align: left;
+  margin-top: 1.0em;
+  margin-bottom: 0.5em;
+}
+div.title + * {
+  margin-top: 0;
+}
+
+td div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content + div.title {
+  margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+  background: #ffffee;
+  border: 1px solid #dddddd;
+  border-left: 4px solid #f0f0f0;
+  padding: 0.5em;
+}
+
+div.listingblock > div.content {
+  border: 1px solid #dddddd;
+  border-left: 5px solid #f0f0f0;
+  background: #f8f8f8;
+  padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+  padding-left: 1.0em;
+  margin-left: 1.0em;
+  margin-right: 10%;
+  border-left: 5px solid #f0f0f0;
+  color: #888;
+}
+
+div.quoteblock > div.attribution {
+  padding-top: 0.5em;
+  text-align: right;
+}
+
+div.verseblock > pre.content {
+  font-family: inherit;
+  font-size: inherit;
+}
+div.verseblock > div.attribution {
+  padding-top: 0.75em;
+  text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+  text-align: left;
+}
+
+div.admonitionblock .icon {
+  vertical-align: top;
+  font-size: 1.1em;
+  font-weight: bold;
+  text-decoration: underline;
+  color: #527bbd;
+  padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+  padding-left: 0.5em;
+  border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+  border-left: 3px solid #dddddd;
+  padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+dt {
+  margin-top: 0.5em;
+  margin-bottom: 0;
+  font-style: normal;
+  color: navy;
+}
+dd > *:first-child {
+  margin-top: 0.1em;
+}
+
+ul, ol {
+    list-style-position: outside;
+}
+ol.arabic {
+  list-style-type: decimal;
+}
+ol.loweralpha {
+  list-style-type: lower-alpha;
+}
+ol.upperalpha {
+  list-style-type: upper-alpha;
+}
+ol.lowerroman {
+  list-style-type: lower-roman;
+}
+ol.upperroman {
+  list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+  margin-top: 0.1em;
+  margin-bottom: 0.1em;
+}
+
+tfoot {
+  font-weight: bold;
+}
+td > div.verse {
+  white-space: pre;
+}
+
+div.hdlist {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+div.hdlist tr {
+  padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+  font-weight: bold;
+}
+td.hdlist1 {
+  vertical-align: top;
+  font-style: normal;
+  padding-right: 0.8em;
+  color: navy;
+}
+td.hdlist2 {
+  vertical-align: top;
+}
+div.hdlist.compact tr {
+  margin: 0;
+  padding-bottom: 0;
+}
+
+.comment {
+  background: yellow;
+}
+
+.footnote, .footnoteref {
+  font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+  vertical-align: super;
+}
+
+#footnotes {
+  margin: 20px 0 20px 0;
+  padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+  margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+  border: none;
+  border-top: 1px solid silver;
+  height: 1px;
+  text-align: left;
+  margin-left: 0;
+  width: 20%;
+  min-width: 100px;
+}
+
+div.colist td {
+  padding-right: 0.5em;
+  padding-bottom: 0.3em;
+  vertical-align: top;
+}
+div.colist td img {
+  margin-top: 0.3em;
+}
+
+@media print {
+  #footer-badges { display: none; }
+}
+
+#toc {
+  margin-bottom: 2.5em;
+}
+
+#toctitle {
+  color: #527bbd;
+  font-size: 1.1em;
+  font-weight: bold;
+  margin-top: 1.0em;
+  margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+div.toclevel2 {
+  margin-left: 2em;
+  font-size: 0.9em;
+}
+div.toclevel3 {
+  margin-left: 4em;
+  font-size: 0.9em;
+}
+div.toclevel4 {
+  margin-left: 6em;
+  font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+tt {
+  font-family: monospace;
+  font-size: inherit;
+  color: navy;
+}
+
+div.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.tableblock > table {
+  border: 3px solid #527bbd;
+}
+thead, p.table.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.table {
+  margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+  border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+  border-left-style: none;
+  border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+  border-top-style: none;
+  border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+.monospaced {
+  font-family: monospace;
+  font-size: inherit;
+  color: navy;
+}
+
+table.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.tableblock {
+  margin-top: 0;
+}
+table.tableblock {
+  border-width: 3px;
+  border-spacing: 0px;
+  border-style: solid;
+  border-color: #527bbd;
+  border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+  border-width: 1px;
+  padding: 4px;
+  border-style: solid;
+  border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+  border-left-style: hidden;
+  border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+  border-top-style: hidden;
+  border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+  border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+  text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+  text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+  text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+  vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+  vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+  vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+  padding-top: 0.5em;
+  padding-bottom: 0.5em;
+  border-top: 2px solid silver;
+  border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+  border-style: none;
+}
+body.manpage div.sectionbody {
+  margin-left: 3em;
+}
+
+@media print {
+  body.manpage div#toc { display: none; }
+}
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = {  // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+  function getText(el) {
+    var text = "";
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+        text += i.data;
+      else if (i.firstChild != null)
+        text += getText(i);
+    }
+    return text;
+  }
+
+  function TocEntry(el, text, toclevel) {
+    this.element = el;
+    this.text = text;
+    this.toclevel = toclevel;
+  }
+
+  function tocEntries(el, toclevels) {
+    var result = new Array;
+    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
+    // Function that scans the DOM tree for header elements (the DOM2
+    // nodeIterator API would be a better technique but not supported by all
+    // browsers).
+    var iterate = function (el) {
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+          var mo = re.exec(i.tagName);
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+          }
+          iterate(i);
+        }
+      }
+    }
+    iterate(el);
+    return result;
+  }
+
+  var toc = document.getElementById("toc");
+  if (!toc) {
+    return;
+  }
+
+  // Delete existing TOC entries in case we're reloading the TOC.
+  var tocEntriesToRemove = [];
+  var i;
+  for (i = 0; i < toc.childNodes.length; i++) {
+    var entry = toc.childNodes[i];
+    if (entry.nodeName == 'div'
+     && entry.getAttribute("class")
+     && entry.getAttribute("class").match(/^toclevel/))
+      tocEntriesToRemove.push(entry);
+  }
+  for (i = 0; i < tocEntriesToRemove.length; i++) {
+    toc.removeChild(tocEntriesToRemove[i]);
+  }
+
+  // Rebuild TOC entries.
+  var entries = tocEntries(document.getElementById("content"), toclevels);
+  for (var i = 0; i < entries.length; ++i) {
+    var entry = entries[i];
+    if (entry.element.id == "")
+      entry.element.id = "_toc_" + i;
+    var a = document.createElement("a");
+    a.href = "#" + entry.element.id;
+    a.appendChild(document.createTextNode(entry.text));
+    var div = document.createElement("div");
+    div.appendChild(a);
+    div.className = "toclevel" + entry.toclevel;
+    toc.appendChild(div);
+  }
+  if (entries.length == 0)
+    toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+  // Delete existing footnote entries in case we're reloading the footnodes.
+  var i;
+  var noteholder = document.getElementById("footnotes");
+  if (!noteholder) {
+    return;
+  }
+  var entriesToRemove = [];
+  for (i = 0; i < noteholder.childNodes.length; i++) {
+    var entry = noteholder.childNodes[i];
+    if (entry.nodeName == 'div' && entry.getAttribute("class") == "footnote")
+      entriesToRemove.push(entry);
+  }
+  for (i = 0; i < entriesToRemove.length; i++) {
+    noteholder.removeChild(entriesToRemove[i]);
+  }
+
+  // Rebuild footnote entries.
+  var cont = document.getElementById("content");
+  var spans = cont.getElementsByTagName("span");
+  var refs = {};
+  var n = 0;
+  for (i=0; i<spans.length; i++) {
+    if (spans[i].className == "footnote") {
+      n++;
+      var note = spans[i].getAttribute("data-note");
+      if (!note) {
+        // Use [\s\S] in place of . so multi-line matches work.
+        // Because JavaScript has no s (dotall) regex flag.
+        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+        spans[i].innerHTML =
+          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+          "' title='View footnote' class='footnote'>" + n + "</a>]";
+        spans[i].setAttribute("data-note", note);
+      }
+      noteholder.innerHTML +=
+        "<div class='footnote' id='_footnote_" + n + "'>" +
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+        n + "</a>. " + note + "</div>";
+      var id =spans[i].getAttribute("id");
+      if (id != null) refs["#"+id] = n;
+    }
+  }
+  if (n == 0)
+    noteholder.parentNode.removeChild(noteholder);
+  else {
+    // Process footnoterefs.
+    for (i=0; i<spans.length; i++) {
+      if (spans[i].className == "footnoteref") {
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+        href = href.match(/#.*/)[0];  // Because IE return full URL.
+        n = refs[href];
+        spans[i].innerHTML =
+          "[<a href='#_footnote_" + n +
+          "' title='View footnote' class='footnote'>" + n + "</a>]";
+      }
+    }
+  }
+},
+
+install: function(toclevels) {
+  var timerId;
+
+  function reinstall() {
+    asciidoc.footnotes();
+    if (toclevels) {
+      asciidoc.toc(toclevels);
+    }
+  }
+
+  function reinstallAndRemoveTimer() {
+    clearInterval(timerId);
+    reinstall();
+  }
+
+  timerId = setInterval(reinstall, 500);
+  if (document.addEventListener)
+    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+  else
+    window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install();
+/*]]>*/
+</script>
+</head>
+<body class="manpage">
+<div id="header">
+<h1>
+Jim Tcl(n) Manual Page
+</h1>
+<h2>NAME</h2>
+<div class="sectionbody">
+<p>Jim Tcl v0.75 -
+   reference manual for the Jim Tcl scripting language
+</p>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_synopsis">SYNOPSIS</h2>
+<div class="sectionbody">
+<div class="literalblock">
+<div class="content">
+<pre><tt>cc &lt;source&gt; -ljim</tt></pre>
+</div></div>
+<div class="paragraph"><p>or</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jimsh [&lt;scriptfile&gt;]
+jimsh -e '&lt;immediate-script&gt;'
+jimsh --version</tt></pre>
+</div></div>
+<div class="ulist"><div class="title">Quick Index</div><ul>
+<li>
+<p>
+<a href="#CommandIndex">Command Reference</a>
+</p>
+</li>
+<li>
+<p>
+<a href="#OperatorPrecedence">Operator Precedence</a>
+</p>
+</li>
+<li>
+<p>
+<a href="#BuiltinVariables">Builtin Variables</a>
+</p>
+</li>
+<li>
+<p>
+<a href="#BackslashSequences">Backslash Sequences</a>
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_introduction">INTRODUCTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Jim Tcl is a small footprint reimplementation of the Tcl scripting language.
+The core language engine is compatible with Tcl 8.5+, while implementing
+a significant subset of the Tcl 8.6 command set, plus additional features
+available only in Jim Tcl.</p></div>
+<div class="paragraph"><p>Some notable differences with Tcl 8.5/8.6 are:</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Object-based I/O (aio), but with a Tcl-compatibility layer
+</p>
+</li>
+<li>
+<p>
+I/O: Support for sockets and pipes including udp, unix domain sockets and IPv6
+</p>
+</li>
+<li>
+<p>
+Integers are 64bit
+</p>
+</li>
+<li>
+<p>
+Support for references (<a href="#_ref"><strong><tt>ref</tt></strong></a>/<a href="#_getref"><strong><tt>getref</tt></strong></a>/<a href="#_setref"><strong><tt>setref</tt></strong></a>) and garbage collection
+</p>
+</li>
+<li>
+<p>
+Builtin dictionary type (<a href="#_dict"><strong><tt>dict</tt></strong></a>) with some limitations compared to Tcl 8.6
+</p>
+</li>
+<li>
+<p>
+<a href="#_env"><strong><tt>env</tt></strong></a> command to access environment variables
+</p>
+</li>
+<li>
+<p>
+Operating system features: <a href="#cmd_1"><strong><tt>os.fork</tt></strong></a>, <a href="#cmd_1"><strong><tt>os.wait</tt></strong></a>, <a href="#cmd_1"><strong><tt>os.uptime</tt></strong></a>, <a href="#_signal"><strong><tt>signal</tt></strong></a>, <a href="#_alarm"><strong><tt>alarm</tt></strong></a>, <a href="#_sleep"><strong><tt>sleep</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+Much better error reporting. <a href="#_info"><strong><tt>info</tt></strong></a> <tt>stacktrace</tt> as a replacement for <em>$errorInfo</em>, <em>$errorCode</em>
+</p>
+</li>
+<li>
+<p>
+Support for "static" variables in procedures
+</p>
+</li>
+<li>
+<p>
+Threads and coroutines are not supported
+</p>
+</li>
+<li>
+<p>
+Command and variable traces are not supported
+</p>
+</li>
+<li>
+<p>
+Built-in command line editing
+</p>
+</li>
+<li>
+<p>
+Expression shorthand syntax: <tt>$(&#8230;)</tt>
+</p>
+</li>
+<li>
+<p>
+Modular build allows many features to be omitted or built as dynamic, loadable modules
+</p>
+</li>
+<li>
+<p>
+Highly suitable for use in an embedded environment
+</p>
+</li>
+<li>
+<p>
+Support for UDP, IPv6, Unix-Domain sockets in addition to TCP sockets
+</p>
+</li>
+</ol></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_recent_changes">RECENT CHANGES</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_changes_between_0_74_and_0_75">Changes between 0.74 and 0.75</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+<a href="#_binary"><strong><tt>binary</tt></strong></a>, <a href="#cmd_3"><strong><tt>pack</tt></strong></a> and <a href="#cmd_3"><strong><tt>unpack</tt></strong></a> now support floating point
+</p>
+</li>
+<li>
+<p>
+<a href="#_file"><strong><tt>file</tt></strong></a> <tt>copy</tt> <em>-force</em> handles source and target as the same file
+</p>
+</li>
+<li>
+<p>
+<a href="#_format"><strong><tt>format</tt></strong></a> now supports <tt>%b</tt> for binary conversion
+</p>
+</li>
+<li>
+<p>
+<a href="#_lsort"><strong><tt>lsort</tt></strong></a> now supports <em>-unique</em> and <em>-real</em>
+</p>
+</li>
+<li>
+<p>
+Add support for half-close with <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>close</tt> ?r|w?
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_socket"><strong><tt>socket</tt></strong></a> <tt>pair</tt> for a bidirectional pipe
+</p>
+</li>
+<li>
+<p>
+Add --random-hash to randomise hash tables for greater security
+</p>
+</li>
+<li>
+<p>
+<a href="#_dict"><strong><tt>dict</tt></strong></a> now supports <em>for</em>, <em>values</em>, <em>incr</em>, <em>append</em>, <em>lappend</em>, <em>update</em>, <em>info</em> and <em>replace</em>
+</p>
+</li>
+<li>
+<p>
+<a href="#_file"><strong><tt>file</tt></strong></a> <tt>stat</tt> no longer requires the variable name
+</p>
+</li>
+</ol></div>
+</div>
+<div class="sect2">
+<h3 id="_changes_between_0_73_and_0_74">Changes between 0.73 and 0.74</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Numbers with leading zeros are treated as decimal, not octal
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>isatty</tt>
+</p>
+</li>
+<li>
+<p>
+Add LFS (64 bit) support for <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>seek</tt>, <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>tell</tt>, <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>copyto</tt>, <a href="#_file"><strong><tt>file</tt></strong></a> <tt>copy</tt>
+</p>
+</li>
+<li>
+<p>
+<a href="#_string"><strong><tt>string</tt></strong></a> <tt>compare</tt> and <a href="#_string"><strong><tt>string</tt></strong></a> <tt>equal</tt> now support <em>-length</em>
+</p>
+</li>
+<li>
+<p>
+<a href="#_glob"><strong><tt>glob</tt></strong></a> now supports <em>-directory</em>
+</p>
+</li>
+</ol></div>
+</div>
+<div class="sect2">
+<h3 id="_changes_between_0_72_and_0_73">Changes between 0.72 and 0.73</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Built-in regexp now support non-capturing parentheses: (?:&#8230;)
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_string"><strong><tt>string</tt></strong></a> <tt>replace</tt>
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_string"><strong><tt>string</tt></strong></a> <tt>totitle</tt>
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_info"><strong><tt>info</tt></strong></a> <tt>statics</tt>
+</p>
+</li>
+<li>
+<p>
+Add <tt>build-jim-ext</tt> for easy separate building of loadable modules (extensions)
+</p>
+</li>
+<li>
+<p>
+<a href="#_local"><strong><tt>local</tt></strong></a> now works with any command, not just procs
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_info"><strong><tt>info</tt></strong></a> <tt>alias</tt> to access the target of an alias
+</p>
+</li>
+<li>
+<p>
+UTF-8 encoding past the basic multilingual plane (BMP) is supported
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_tcl_prefix"><strong><tt>tcl::prefix</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_history"><strong><tt>history</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+Most extensions are now enabled by default
+</p>
+</li>
+<li>
+<p>
+Add support for namespaces and the <a href="#_namespace"><strong><tt>namespace</tt></strong></a> command
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_apply"><strong><tt>apply</tt></strong></a>
+</p>
+</li>
+</ol></div>
+</div>
+<div class="sect2">
+<h3 id="_changes_between_0_71_and_0_72">Changes between 0.71 and 0.72</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+procs now allow <em>args</em> and optional parameters in any position
+</p>
+</li>
+<li>
+<p>
+Add Tcl-compatible expr functions, <tt>rand()</tt>, <tt>srand()</tt> and <tt>pow()</tt>
+</p>
+</li>
+<li>
+<p>
+Add support for the <em>-force</em> option to <a href="#_file"><strong><tt>file</tt></strong></a> <tt>delete</tt>
+</p>
+</li>
+<li>
+<p>
+Better diagnostics when <a href="#_source"><strong><tt>source</tt></strong></a> fails to load a script with a missing quote or bracket
+</p>
+</li>
+<li>
+<p>
+New <tt>tcl_platform(pathSeparator)</tt>
+</p>
+</li>
+<li>
+<p>
+Add support settings the modification time with <a href="#_file"><strong><tt>file</tt></strong></a> <tt>mtime</tt>
+</p>
+</li>
+<li>
+<p>
+<a href="#_exec"><strong><tt>exec</tt></strong></a> is now fully supported on win32 (mingw32)
+</p>
+</li>
+<li>
+<p>
+<a href="#_file"><strong><tt>file</tt></strong></a> <tt>join</tt>, <a href="#_pwd"><strong><tt>pwd</tt></strong></a>, <a href="#_glob"><strong><tt>glob</tt></strong></a> etc. now work for mingw32
+</p>
+</li>
+<li>
+<p>
+Line editing is now supported for the win32 console (mingw32)
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>listen</tt> command
+</p>
+</li>
+</ol></div>
+</div>
+<div class="sect2">
+<h3 id="_changes_between_0_70_and_0_71">Changes between 0.70 and 0.71</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Allow <em>args</em> to be renamed in procs
+</p>
+</li>
+<li>
+<p>
+Add <tt>$(&#8230;)</tt> shorthand syntax for expressions
+</p>
+</li>
+<li>
+<p>
+Add automatic reference variables in procs with <tt>&amp;var</tt> syntax
+</p>
+</li>
+<li>
+<p>
+Support <tt>jimsh --version</tt>
+</p>
+</li>
+<li>
+<p>
+Additional variables in <tt>tcl_platform()</tt>
+</p>
+</li>
+<li>
+<p>
+<a href="#_local"><strong><tt>local</tt></strong></a> procs now push existing commands and <a href="#_upcall"><strong><tt>upcall</tt></strong></a> can call them
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_loop"><strong><tt>loop</tt></strong></a> command (TclX compatible)
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>buffering</tt> command
+</p>
+</li>
+<li>
+<p>
+<a href="#_info"><strong><tt>info</tt></strong></a> <tt>complete</tt> can now return the missing character
+</p>
+</li>
+<li>
+<p>
+<a href="#_binary"><strong><tt>binary</tt></strong></a> <tt>format</tt> and <a href="#_binary"><strong><tt>binary</tt></strong></a> <tt>scan</tt> are now (optionally) supported
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_string"><strong><tt>string</tt></strong></a> <tt>byterange</tt>
+</p>
+</li>
+<li>
+<p>
+Built-in regexp now support non-greedy repetition (*?, +?, ??)
+</p>
+</li>
+</ol></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_tcl_introduction">TCL INTRODUCTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Tcl stands for <em>tool command language</em> and is pronounced <em>tickle.</em>
+It is actually two things: a language and a library.</p></div>
+<div class="paragraph"><p>First, Tcl is a simple textual language, intended primarily for
+issuing commands to interactive programs such as text editors,
+debuggers, illustrators, and shells.  It has a simple syntax and is also
+programmable, so Tcl users can write command procedures to provide more
+powerful commands than those in the built-in set.</p></div>
+<div class="paragraph"><p>Second, Tcl is a library package that can be embedded in application
+programs.  The Tcl library consists of a parser for the Tcl language,
+routines to implement the Tcl built-in commands, and procedures that
+allow each application to extend Tcl with additional commands specific
+to that application.  The application program generates Tcl commands and
+passes them to the Tcl parser for execution.  Commands may be generated
+by reading characters from an input source, or by associating command
+strings with elements of the application&#8217;s user interface, such as menu
+entries, buttons, or keystrokes.</p></div>
+<div class="paragraph"><p>When the Tcl library receives commands it parses them into component
+fields and executes built-in commands directly.  For commands implemented
+by the application, Tcl calls back to the application to execute the
+commands.  In many cases commands will invoke recursive invocations of the
+Tcl interpreter by passing in additional strings to execute (procedures,
+looping commands, and conditional commands all work in this way).</p></div>
+<div class="paragraph"><p>An application program gains three advantages by using Tcl for its command
+language.  First, Tcl provides a standard syntax:  once users know Tcl,
+they will be able to issue commands easily to any Tcl-based application.
+Second, Tcl provides programmability.  All a Tcl application needs
+to do is to implement a few application-specific low-level commands.
+Tcl provides many utility commands plus a general programming interface
+for building up complex command procedures.  By using Tcl, applications
+need not re-implement these features.</p></div>
+<div class="paragraph"><p>Third, Tcl can be used as a common language for communicating between
+applications.  Inter-application communication is not built into the
+Tcl core described here, but various add-on libraries, such as the Tk
+toolkit, allow applications to issue commands to each other.  This makes
+it possible for applications to work together in much more powerful ways
+than was previously possible.</p></div>
+<div class="paragraph"><p>Fourth, Jim Tcl includes a command processor, <tt>jimsh</tt>, which can be
+used to run standalone Tcl scripts, or to run Tcl commands interactively.</p></div>
+<div class="paragraph"><p>This manual page focuses primarily on the Tcl language.  It describes
+the language syntax and the built-in commands that will be available
+in any application based on Tcl.  The individual library procedures are
+described in more detail in separate manual pages, one per procedure.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_jimsh_command_interpreter">JIMSH COMMAND INTERPRETER</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>A simple, but powerful command processor, <tt>jimsh</tt>, is part of Jim Tcl.
+It may be invoked in interactive mode as:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jimsh</tt></pre>
+</div></div>
+<div class="paragraph"><p>or to process the Tcl script in a file with:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jimsh filename</tt></pre>
+</div></div>
+<div class="paragraph"><p>It may also be invoked to execute an immediate script with:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jimsh -e "script"</tt></pre>
+</div></div>
+<div class="sect2">
+<h3 id="_interactive_mode">Interactive Mode</h3>
+<div class="paragraph"><p>Interactive mode reads Tcl commands from standard input, evaluates
+those commands and prints the results.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>$ jimsh
+Welcome to Jim version 0.73, Copyright (c) 2005-8 Salvatore Sanfilippo
+. info version
+0.73
+. lsort [info commands p*]
+package parray pid popen proc puts pwd
+. foreach i {a b c} {
+{&gt; puts $i
+{&gt; }
+a
+b
+c
+. bad
+invalid command name "bad"
+[error] . exit
+$</tt></pre>
+</div></div>
+<div class="paragraph"><p>If <tt>jimsh</tt> is configured with line editing (it is by default) and a VT-100-compatible
+terminal is detected, Emacs-style line editing commands are available, including:
+arrow keys, <tt>^W</tt> to erase a word, <tt>^U</tt> to erase the line, <tt>^R</tt> for reverse incremental search
+in history. Additionally, the <tt>h</tt> command may be used to display the command history.</p></div>
+<div class="paragraph"><p>Command line history is automatically saved and loaded from <tt>~/.jim_history</tt></p></div>
+<div class="paragraph"><p>In interactive mode, <tt>jimsh</tt> automatically runs the script <tt>~/.jimrc</tt> at startup
+if it exists.</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_interpreters">INTERPRETERS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The central data structure in Tcl is an interpreter (C type <em>Jim_Interp</em>).
+An interpreter consists of a set of command bindings, a set of variable
+values, and a few other miscellaneous pieces of state.  Each Tcl command
+is interpreted in the context of a particular interpreter.</p></div>
+<div class="paragraph"><p>Some Tcl-based applications will maintain multiple interpreters
+simultaneously, each associated with a different widget or portion of
+the application.  Interpreters are relatively lightweight structures.
+They can be created and deleted quickly, so application programmers should
+feel free to use multiple interpreters if that simplifies the application.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_data_types">DATA TYPES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Tcl supports only one type of data:  strings.  All commands, all arguments
+to commands, all command results, and all variable values are strings.</p></div>
+<div class="paragraph"><p>Where commands require numeric arguments or return numeric results,
+the arguments and results are passed as strings.  Many commands expect
+their string arguments to have certain formats, but this interpretation
+is up to the individual commands.  For example, arguments often contain
+Tcl command strings, which may get executed as part of the commands.
+The easiest way to understand the Tcl interpreter is to remember that
+everything is just an operation on a string.  In many cases Tcl constructs
+will look similar to more structured constructs from other languages.
+However, the Tcl constructs are not structured at all; they are just
+strings of characters, and this gives them a different behaviour than
+the structures they may look like.</p></div>
+<div class="paragraph"><p>Although the exact interpretation of a Tcl string depends on who is doing
+the interpretation, there are three common forms that strings take:
+commands, expressions, and lists.  The major sections below discuss
+these three forms in more detail.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_basic_command_syntax">BASIC COMMAND SYNTAX</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The Tcl language has syntactic similarities to both the Unix shells
+and Lisp.  However, the interpretation of commands is different
+in Tcl than in either of those other two systems.
+A Tcl command string consists of one or more commands separated
+by newline characters or semi-colons.
+Each command consists of a collection of fields separated by
+white space (spaces or tabs).
+The first field must be the name of a command, and the
+additional fields, if any, are arguments that will be passed to
+that command.  For example, the command:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a 22</tt></pre>
+</div></div>
+<div class="paragraph"><p>has three fields:  the first, <a href="#_set"><strong><tt>set</tt></strong></a>, is the name of a Tcl command, and
+the last two, <em>a</em> and <em>22</em>, will be passed as arguments to
+the <a href="#_set"><strong><tt>set</tt></strong></a> command.  The command name may refer either to a built-in
+Tcl command, an application-specific command bound in with the library
+procedure <em>Jim_CreateCommand</em>, or a command procedure defined with the
+<a href="#_proc"><strong><tt>proc</tt></strong></a> built-in command.</p></div>
+<div class="paragraph"><p>Arguments are passed literally as text strings.  Individual commands may
+interpret those strings in any fashion they wish.  The <a href="#_set"><strong><tt>set</tt></strong></a> command,
+for example, will treat its first argument as the name of a variable
+and its second argument as a string value to assign to that variable.
+For other commands arguments may be interpreted as integers, lists,
+file names, or Tcl commands.</p></div>
+<div class="paragraph"><p>Command names should normally be typed completely (e.g. no abbreviations).
+However, if the Tcl interpreter cannot locate a command it invokes a
+special command named <a href="#_unknown"><strong><tt>unknown</tt></strong></a> which attempts to find or create the
+command.</p></div>
+<div class="paragraph"><p>For example, at many sites <a href="#_unknown"><strong><tt>unknown</tt></strong></a> will search through library
+directories for the desired command and create it as a Tcl procedure if
+it is found.  The <a href="#_unknown"><strong><tt>unknown</tt></strong></a> command often provides automatic completion
+of abbreviated commands, but usually only for commands that were typed
+interactively.</p></div>
+<div class="paragraph"><p>It&#8217;s probably a bad idea to use abbreviations in command scripts and
+other forms that will be re-used over time:  changes to the command set
+may cause abbreviations to become ambiguous, resulting in scripts that
+no longer work.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_comments">COMMENTS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>If the first non-blank character in a command is <tt>#</tt>, then everything
+from the <tt>#</tt> up through the next newline character is treated as
+a comment and ignored.  When comments are embedded inside nested
+commands (e.g. fields enclosed in braces) they must have properly-matched
+braces (this is necessary because when Tcl parses the top-level command
+it doesn&#8217;t yet know that the nested field will be used as a command so
+it cannot process the nested comment character as a comment).</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_grouping_arguments_with_double_quotes">GROUPING ARGUMENTS WITH DOUBLE-QUOTES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Normally each argument field ends at the next white space, but
+double-quotes may be used to create arguments with embedded space.</p></div>
+<div class="paragraph"><p>If an argument field begins with a double-quote, then the argument isn&#8217;t
+terminated by white space (including newlines) or a semi-colon (see below
+for information on semi-colons); instead it ends at the next double-quote
+character.  The double-quotes are not included in the resulting argument.
+For example, the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a "This is a single argument"</tt></pre>
+</div></div>
+<div class="paragraph"><p>will pass two arguments to <a href="#_set"><strong><tt>set</tt></strong></a>:  <em>a</em> and <em>This is a single argument</em>.</p></div>
+<div class="paragraph"><p>Within double-quotes, command substitutions, variable substitutions,
+and backslash substitutions still occur, as described below.  If the
+first character of a command field is not a quote, then quotes receive
+no special interpretation in the parsing of that field.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_grouping_arguments_with_braces">GROUPING ARGUMENTS WITH BRACES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Curly braces may also be used for grouping arguments.  They are similar
+to quotes except for two differences.  First, they nest; this makes them
+easier to use for complicated arguments like nested Tcl command strings.
+Second, the substitutions described below for commands, variables, and
+backslashes do <strong>not</strong> occur in arguments enclosed in braces, so braces
+can be used to prevent substitutions where they are undesirable.</p></div>
+<div class="paragraph"><p>If an argument field begins with a left brace, then the argument ends
+at the matching right brace.  Tcl will strip off the outermost layer
+of braces and pass the information between the braces to the command
+without any further modification.  For example, in the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a {xyz a {b c d}}</tt></pre>
+</div></div>
+<div class="paragraph"><p>the <a href="#_set"><strong><tt>set</tt></strong></a> command will receive two arguments: <em>a</em>
+and <em>xyz a {b c d}</em>.</p></div>
+<div class="paragraph"><p>When braces or quotes are in effect, the matching brace or quote need
+not be on the same line as the starting quote or brace; in this case
+the newline will be included in the argument field along with any other
+characters up to the matching brace or quote.  For example, the <a href="#_eval"><strong><tt>eval</tt></strong></a>
+command takes one argument, which is a command string; <a href="#_eval"><strong><tt>eval</tt></strong></a> invokes
+the Tcl interpreter to execute the command string.  The command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>eval {
+  set a 22
+  set b 33
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will assign the value <em>22</em> to <em>a</em> and <em>33</em> to <em>b</em>.</p></div>
+<div class="paragraph"><p>If the first character of a command field is not a left
+brace, then neither left nor right
+braces in the field will be treated specially (except as part of
+variable substitution; see below).</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_command_substitution_with_brackets">COMMAND SUBSTITUTION WITH BRACKETS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>If an open bracket occurs in a field of a command, then command
+substitution occurs (except for fields enclosed in braces).  All of the
+text up to the matching close bracket is treated as a Tcl command and
+executed immediately.  Then the result of that command is substituted
+for the bracketed text.  For example, consider the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a [set b]</tt></pre>
+</div></div>
+<div class="paragraph"><p>When the <a href="#_set"><strong><tt>set</tt></strong></a> command has only a single argument, it is the name of a
+variable and <a href="#_set"><strong><tt>set</tt></strong></a> returns the contents of that variable.  In this case,
+if variable <em>b</em> has the value <em>foo</em>, then the command above is equivalent
+to the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a foo</tt></pre>
+</div></div>
+<div class="paragraph"><p>Brackets can be used in more complex ways.  For example, if the variable
+<em>b</em> has the value <em>foo</em> and the variable <em>c</em> has the value <em>gorp</em>,
+then the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a xyz[set b].[set c]</tt></pre>
+</div></div>
+<div class="paragraph"><p>is equivalent to the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a xyzfoo.gorp</tt></pre>
+</div></div>
+<div class="paragraph"><p>A bracketed command may contain multiple commands separated by newlines
+or semi-colons in the usual fashion.  In this case the value of the last
+command is used for substitution.  For example, the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a x[set b 22
+expr $b+2]x</tt></pre>
+</div></div>
+<div class="paragraph"><p>is equivalent to the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a x24x</tt></pre>
+</div></div>
+<div class="paragraph"><p>If a field is enclosed in braces then the brackets and the characters
+between them are not interpreted specially; they are passed through to
+the argument verbatim.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_variable_substitution_with">VARIABLE SUBSTITUTION WITH $</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The dollar sign (<tt>$</tt>) may be used as a special shorthand form for
+substituting variable values.  If <tt>$</tt> appears in an argument that isn&#8217;t
+enclosed in braces then variable substitution will occur.  The characters
+after the <tt>$</tt>, up to the first character that isn&#8217;t a number, letter,
+or underscore, are taken as a variable name and the string value of that
+variable is substituted for the name.</p></div>
+<div class="paragraph"><p>For example, if variable <em>foo</em> has the value <em>test</em>, then the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a $foo.c</tt></pre>
+</div></div>
+<div class="paragraph"><p>is equivalent to the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a test.c</tt></pre>
+</div></div>
+<div class="paragraph"><p>There are two special forms for variable substitution.  If the next
+character after the name of the variable is an open parenthesis, then
+the variable is assumed to be an array name, and all of the characters
+between the open parenthesis and the next close parenthesis are taken as
+an index into the array.  Command substitutions and variable substitutions
+are performed on the information between the parentheses before it is
+used as an index.</p></div>
+<div class="paragraph"><p>For example, if the variable <em>x</em> is an array with one element named
+<em>first</em> and value <em>87</em> and another element named <em>14</em> and value <em>more</em>,
+then the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a xyz$x(first)zyx</tt></pre>
+</div></div>
+<div class="paragraph"><p>is equivalent to the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a xyz87zyx</tt></pre>
+</div></div>
+<div class="paragraph"><p>If the variable <em>index</em> has the value <em>14</em>, then the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a xyz$x($index)zyx</tt></pre>
+</div></div>
+<div class="paragraph"><p>is equivalent to the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a xyzmorezyx</tt></pre>
+</div></div>
+<div class="paragraph"><p>For more information on arrays, see VARIABLES AND ARRAYS below.</p></div>
+<div class="paragraph"><p>The second special form for variables occurs when the dollar sign is
+followed by an open curly brace.  In this case the variable name consists
+of all the characters up to the next curly brace.</p></div>
+<div class="paragraph"><p>Array references are not possible in this form:  the name between braces
+is assumed to refer to a scalar variable.  For example, if variable
+<em>foo</em> has the value <em>test</em>, then the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a abc${foo}bar</tt></pre>
+</div></div>
+<div class="paragraph"><p>is equivalent to the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a abctestbar</tt></pre>
+</div></div>
+<div class="paragraph"><p>Variable substitution does not occur in arguments that are enclosed in
+braces:  the dollar sign and variable name are passed through to the
+argument verbatim.</p></div>
+<div class="paragraph"><p>The dollar sign abbreviation is simply a shorthand form.  <tt>$a</tt> is
+completely equivalent to <tt>[set a]</tt>; it is provided as a convenience
+to reduce typing.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_separating_commands_with_semi_colons">SEPARATING COMMANDS WITH SEMI-COLONS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Normally, each command occupies one line (the command is terminated by a
+newline character).  However, semi-colon (<tt>;</tt>) is treated as a command
+separator character; multiple commands may be placed on one line by
+separating them with a semi-colon.  Semi-colons are not treated as
+command separators if they appear within curly braces or double-quotes.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_backslash_substitution">BACKSLASH SUBSTITUTION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Backslashes may be used to insert non-printing characters into command
+fields and also to insert special characters like braces and brackets
+into fields without them being interpreted specially as described above.</p></div>
+<div class="paragraph"><p>The backslash sequences understood by the Tcl interpreter are
+listed below.  In each case, the backslash
+sequence is replaced by the given character:</p></div>
+<div class="dlist" id="BackslashSequences"><dl>
+<dt class="hdlist1">
+<tt>\b</tt>
+</dt>
+<dd>
+<p>
+    Backspace (0x8)
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\f</tt>
+</dt>
+<dd>
+<p>
+    Form feed (0xc)
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\n</tt>
+</dt>
+<dd>
+<p>
+    Newline (0xa)
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\r</tt>
+</dt>
+<dd>
+<p>
+    Carriage-return (0xd).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\t</tt>
+</dt>
+<dd>
+<p>
+    Tab (0x9).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\v</tt>
+</dt>
+<dd>
+<p>
+    Vertical tab (0xb).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\{</tt>
+</dt>
+<dd>
+<p>
+    Left brace ({).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\}</tt>
+</dt>
+<dd>
+<p>
+    Right brace (}).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\[</tt>
+</dt>
+<dd>
+<p>
+    Open bracket ([).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\]</tt>
+</dt>
+<dd>
+<p>
+    Close bracket (]).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\$</tt>
+</dt>
+<dd>
+<p>
+    Dollar sign ($).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\&lt;space&gt;</tt>
+</dt>
+<dd>
+<p>
+    Space ( ): doesn&#8217;t terminate argument.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\;</tt>
+</dt>
+<dd>
+<p>
+    Semi-colon: doesn&#8217;t terminate command.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\"</tt>
+</dt>
+<dd>
+<p>
+    Double-quote.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\&lt;newline&gt;</tt>
+</dt>
+<dd>
+<p>
+    Nothing:  this joins two lines together
+    into a single line.  This backslash feature is unique in that
+    it will be applied even when the sequence occurs within braces.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\\</tt>
+</dt>
+<dd>
+<p>
+    Backslash (<em>\</em>).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\ddd</tt>
+</dt>
+<dd>
+<p>
+    The digits <tt><em>ddd</em></tt> (one, two, or three of them) give the octal value of
+    the character.  Note that Jim supports null characters in strings.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\unnnn</tt>
+</dt>
+<dt class="hdlist1">
+<tt>\u{nnn}</tt>
+</dt>
+<dt class="hdlist1">
+<tt>\Unnnnnnnn</tt>
+</dt>
+<dd>
+<p>
+    The UTF-8 encoding of the unicode codepoint represented by the hex digits, <tt><em>nnnn</em></tt>, is inserted.
+    The <em>u</em> form allows for one to four hex digits.
+    The <em>U</em> form allows for one to eight hex digits.
+    The <em>u{nnn}</em> form allows for one to eight hex digits, but makes it easier to insert
+    characters UTF-8 characters which are followed by a hex digit.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>For example, in the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a \{x\[\ yz\141</tt></pre>
+</div></div>
+<div class="paragraph"><p>the second argument to <a href="#_set"><strong><tt>set</tt></strong></a> will be <tt>{x[ yza</tt>.</p></div>
+<div class="paragraph"><p>If a backslash is followed by something other than one of the options
+described above, then the backslash is transmitted to the argument
+field without any special processing, and the Tcl scanner continues
+normal processing with the next character.  For example, in the
+command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set \*a \\\{foo</tt></pre>
+</div></div>
+<div class="paragraph"><p>The first argument to <a href="#_set"><strong><tt>set</tt></strong></a> will be <tt>\*a</tt> and the second
+argument will be <tt>\{foo</tt>.</p></div>
+<div class="paragraph"><p>If an argument is enclosed in braces, then backslash sequences inside
+the argument are parsed but no substitution occurs (except for
+backslash-newline):  the backslash
+sequence is passed through to the argument as is, without making
+any special interpretation of the characters in the backslash sequence.
+In particular, backslashed braces are not counted in locating the
+matching right brace that terminates the argument.
+For example, in the
+command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a {\{abc}</tt></pre>
+</div></div>
+<div class="paragraph"><p>the second argument to <a href="#_set"><strong><tt>set</tt></strong></a> will be <tt>\{abc</tt>.</p></div>
+<div class="paragraph"><p>This backslash mechanism is not sufficient to generate absolutely
+any argument structure; it only covers the
+most common cases.  To produce particularly complicated arguments
+it is probably easiest to use the <a href="#_format"><strong><tt>format</tt></strong></a> command along with
+command substitution.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_string_and_list_index_specifications">STRING AND LIST INDEX SPECIFICATIONS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Many string and list commands take one or more <em>index</em> parameters which
+specify a position in the string relative to the start or end of the string/list.</p></div>
+<div class="paragraph"><p>The index may be one of the following forms:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>integer</tt>
+</dt>
+<dd>
+<p>
+    A simple integer, where <em>0</em> refers to the first element of the string
+    or list.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>integer+integer</tt> or
+</dt>
+<dt class="hdlist1">
+<tt>integer-integer</tt>
+</dt>
+<dd>
+<p>
+    The sum or difference of the two integers. e.g. <tt>2+3</tt> refers to the 5th element.
+    This is useful when used with (e.g.) <tt>$i+1</tt> rather than the more verbose
+    <tt>[expr {$i+1}]</tt>
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>end</tt>
+</dt>
+<dd>
+<p>
+    The last element of the string or list.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>end-integer</tt>
+</dt>
+<dd>
+<p>
+    The <em>nth-from-last</em> element of the string or list.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_command_summary">COMMAND SUMMARY</h2>
+<div class="sectionbody">
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+A command is just a string.
+</p>
+</li>
+<li>
+<p>
+Within a string commands are separated by newlines or semi-colons
+   (unless the newline or semi-colon is within braces or brackets
+   or is backslashed).
+</p>
+</li>
+<li>
+<p>
+A command consists of fields.  The first field is the name of the command.
+   The other fields are strings that are passed to that command as arguments.
+</p>
+</li>
+<li>
+<p>
+Fields are normally separated by white space.
+</p>
+</li>
+<li>
+<p>
+Double-quotes allow white space and semi-colons to appear within
+   a single argument.
+   Command substitution, variable substitution, and backslash substitution
+   still occur inside quotes.
+</p>
+</li>
+<li>
+<p>
+Braces defer interpretation of special characters.
+   If a field begins with a left brace, then it consists of everything
+   between the left brace and the matching right brace. The
+   braces themselves are not included in the argument.
+   No further processing is done on the information between the braces
+   except that backslash-newline sequences are eliminated.
+</p>
+</li>
+<li>
+<p>
+If a field doesn&#8217;t begin with a brace then backslash,
+   variable, and command substitution are done on the field.  Only a
+   single level of processing is done:  the results of one substitution
+   are not scanned again for further substitutions or any other
+   special treatment.  Substitution can
+   occur on any field of a command, including the command name
+   as well as the arguments.
+</p>
+</li>
+<li>
+<p>
+If the first non-blank character of a command is a <tt>#</tt>, everything
+   from the <tt>#</tt> up through the next newline is treated as a comment
+   and ignored.
+</p>
+</li>
+</ol></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_expressions">EXPRESSIONS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The second major interpretation applied to strings in Tcl is
+as expressions.  Several commands, such as <a href="#_expr"><strong><tt>expr</tt></strong></a>, <a href="#_for"><strong><tt>for</tt></strong></a>,
+and <a href="#_if"><strong><tt>if</tt></strong></a>, treat one or more of their arguments as expressions
+and call the Tcl expression processors (<em>Jim_ExprLong</em>,
+<em>Jim_ExprBoolean</em>, etc.) to evaluate them.</p></div>
+<div class="paragraph"><p>The operators permitted in Tcl expressions are a subset of
+the operators permitted in C expressions, and they have the
+same meaning and precedence as the corresponding C operators.
+Expressions almost always yield numeric results
+(integer or floating-point values).
+For example, the expression</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>8.2 + 6</tt></pre>
+</div></div>
+<div class="paragraph"><p>evaluates to 14.2.</p></div>
+<div class="paragraph"><p>Tcl expressions differ from C expressions in the way that
+operands are specified, and in that Tcl expressions support
+non-numeric operands and string comparisons.</p></div>
+<div class="paragraph"><p>A Tcl expression consists of a combination of operands, operators,
+and parentheses.</p></div>
+<div class="paragraph"><p>White space may be used between the operands and operators and
+parentheses; it is ignored by the expression processor.
+Where possible, operands are interpreted as integer values.</p></div>
+<div class="paragraph"><p>Integer values may be specified in decimal (the normal case) or in
+hexadecimal (if the first two characters of the operand are <em>0x</em>).
+Note that Jim Tcl does <strong>not</strong> treat numbers with leading zeros as octal.</p></div>
+<div class="paragraph"><p>If an operand does not have one of the integer formats given
+above, then it is treated as a floating-point number if that is
+possible.  Floating-point numbers may be specified in any of the
+ways accepted by an ANSI-compliant C compiler (except that the
+<em>f</em>, <em>F</em>, <em>l</em>, and <em>L</em> suffixes will not be permitted in
+most installations).  For example, all of the
+following are valid floating-point numbers:  2.1, 3., 6e4, 7.91e+16.</p></div>
+<div class="paragraph"><p>If no numeric interpretation is possible, then an operand is left
+as a string (and only a limited set of operators may be applied to
+it).</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Operands may be specified in any of the following ways:
+</p>
+</li>
+<li>
+<p>
+As a numeric value, either integer or floating-point.
+</p>
+</li>
+<li>
+<p>
+As a Tcl variable, using standard <em>$</em> notation.
+The variable&#8217;s value will be used as the operand.
+</p>
+</li>
+<li>
+<p>
+As a string enclosed in double-quotes.
+The expression parser will perform backslash, variable, and
+command substitutions on the information between the quotes,
+and use the resulting value as the operand
+</p>
+</li>
+<li>
+<p>
+As a string enclosed in braces.
+The characters between the open brace and matching close brace
+will be used as the operand without any substitutions.
+</p>
+</li>
+<li>
+<p>
+As a Tcl command enclosed in brackets.
+The command will be executed and its result will be used as
+the operand.
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>Where substitutions occur above (e.g. inside quoted strings), they
+are performed by the expression processor.
+However, an additional layer of substitution may already have
+been performed by the command parser before the expression
+processor was called.</p></div>
+<div class="paragraph"><p>As discussed below, it is usually best to enclose expressions
+in braces to prevent the command parser from performing substitutions
+on the contents.</p></div>
+<div class="paragraph"><p>For some examples of simple expressions, suppose the variable <em>a</em> has
+the value 3 and the variable <em>b</em> has the value 6.  Then the expression
+on the left side of each of the lines below will evaluate to the value
+on the right side of the line:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>$a + 3.1                6.1
+2 + "$a.$b"             5.6
+4*[llength "6 2"]       8
+{word one} &lt; "word $a"  0</tt></pre>
+</div></div>
+<div class="paragraph"><p>The valid operators are listed below, grouped in decreasing order
+of precedence:</p></div>
+<div class="dlist" id="OperatorPrecedence"><dl>
+<dt class="hdlist1">
+<tt>int() double() round() abs(), rand(), srand()</tt>
+</dt>
+<dd>
+<p>
+    Unary functions (except rand() which takes no arguments)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+<tt><em>int()</em></tt> converts the numeric argument to an integer by truncating down.
+</p>
+</li>
+<li>
+<p>
+<tt><em>double()</em></tt> converts the numeric argument to floating point.
+</p>
+</li>
+<li>
+<p>
+<tt><em>round()</em></tt> converts the numeric argument to the closest integer value.
+</p>
+</li>
+<li>
+<p>
+<tt><em>abs()</em></tt> takes the absolute value of the numeric argument.
+</p>
+</li>
+<li>
+<p>
+<tt><em>rand()</em></tt> takes the absolute value of the numeric argument.
+</p>
+</li>
+<li>
+<p>
+<tt><em>rand()</em></tt> returns a pseudo-random floating-point value in the range (0,1).
+</p>
+</li>
+<li>
+<p>
+<tt><em>srand()</em></tt> takes an integer argument to (re)seed the random number generator. Returns the first random number from that seed.
+</p>
+</li>
+</ul></div>
+</dd>
+<dt class="hdlist1">
+<tt>sin() cos() tan() asin() acos() atan() sinh() cosh() tanh() ceil() floor() exp() log() log10() sqrt()</tt>
+</dt>
+<dd>
+<p>
+    Unary math functions.
+    If Jim is compiled with math support, these functions are available.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>- + ~ !</tt>
+</dt>
+<dd>
+<p>
+    Unary minus, unary plus, bit-wise NOT, logical NOT.  None of these operands
+    may be applied to string operands, and bit-wise NOT may be
+    applied only to integers.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>** pow(x,y)</tt>
+</dt>
+<dd>
+<p>
+    Power. e.g. <em>x<sup>y</sup></em>. If Jim is compiled with math support, supports doubles and
+    integers. Otherwise supports integers only. (Note that the math-function form
+    has the same highest precedence)
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>* / %</tt>
+</dt>
+<dd>
+<p>
+    Multiply, divide, remainder.  None of these operands may be
+    applied to string operands, and remainder may be applied only
+    to integers.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>+ -</tt>
+</dt>
+<dd>
+<p>
+    Add and subtract.  Valid for any numeric operands.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&lt;&lt;  &gt;&gt; &lt;&lt;&lt; &gt;&gt;&gt;</tt>
+</dt>
+<dd>
+<p>
+    Left and right shift, left and right rotate.  Valid for integer operands only.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&lt;  &gt;  &lt;=  &gt;=</tt>
+</dt>
+<dd>
+<p>
+    Boolean less, greater, less than or equal, and greater than or equal.
+    Each operator produces 1 if the condition is true, 0 otherwise.
+    These operators may be applied to strings as well as numeric operands,
+    in which case string comparison is used.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>==  !=</tt>
+</dt>
+<dd>
+<p>
+    Boolean equal and not equal.  Each operator produces a zero/one result.
+    Valid for all operand types. <strong>Note</strong> that values will be converted to integers
+    if possible, then floating point types, and finally strings will be compared.
+    It is recommended that <em>eq</em> and <em>ne</em> should be used for string comparison.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>eq ne</tt>
+</dt>
+<dd>
+<p>
+    String equal and not equal.  Uses the string value directly without
+    attempting to convert to a number first.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>in ni</tt>
+</dt>
+<dd>
+<p>
+    String in list and not in list. For <em>in</em>, result is 1 if the left operand (as a string)
+    is contained in the right operand (as a list), or 0 otherwise. The result for
+    <tt>{$a ni $list}</tt> is equivalent to <tt>{!($a in $list)}</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&amp;</tt>
+</dt>
+<dd>
+<p>
+    Bit-wise AND.  Valid for integer operands only.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>|</tt>
+</dt>
+<dd>
+<p>
+    Bit-wise OR.  Valid for integer operands only.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>^</tt>
+</dt>
+<dd>
+<p>
+    Bit-wise exclusive OR.  Valid for integer operands only.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&amp;&amp;</tt>
+</dt>
+<dd>
+<p>
+    Logical AND.  Produces a 1 result if both operands are non-zero, 0 otherwise.
+    Valid for numeric operands only (integers or floating-point).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>||</tt>
+</dt>
+<dd>
+<p>
+    Logical OR.  Produces a 0 result if both operands are zero, 1 otherwise.
+    Valid for numeric operands only (integers or floating-point).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>x ? y : z</tt>
+</dt>
+<dd>
+<p>
+    If-then-else, as in C.  If <tt><em>x</em></tt>
+    evaluates to non-zero, then the result is the value of <tt><em>y</em></tt>.
+    Otherwise the result is the value of <tt><em>z</em></tt>.
+    The <tt><em>x</em></tt> operand must have a numeric value, while <tt><em>y</em></tt> and <tt><em>z</em></tt> can
+    be of any type.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>See the C manual for more details on the results
+produced by each operator.
+All of the binary operators group left-to-right within the same
+precedence level.  For example, the expression</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>4*2 &lt; 7</tt></pre>
+</div></div>
+<div class="paragraph"><p>evaluates to 0.</p></div>
+<div class="paragraph"><p>The <tt>&amp;&amp;</tt>, <tt>||</tt>, and <tt>?:</tt> operators have <em>lazy evaluation</em>, just as
+in C, which means that operands are not evaluated if they are not
+needed to determine the outcome.  For example, in</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>$v ? [a] : [b]</tt></pre>
+</div></div>
+<div class="paragraph"><p>only one of <tt>[a]</tt> or <tt>[b]</tt> will actually be evaluated,
+depending on the value of <tt>$v</tt>.</p></div>
+<div class="paragraph"><p>All internal computations involving integers are done with the C
+type <em>long long</em> if available, or <em>long</em> otherwise, and all internal
+computations involving floating-point are done with the C type
+<em>double</em>.</p></div>
+<div class="paragraph"><p>When converting a string to floating-point, exponent overflow is
+detected and results in a Tcl error.
+For conversion to integer from string, detection of overflow depends
+on the behaviour of some routines in the local C library, so it should
+be regarded as unreliable.
+In any case, overflow and underflow are generally not detected
+reliably for intermediate results.</p></div>
+<div class="paragraph"><p>Conversion among internal representations for integer, floating-point,
+and string operands is done automatically as needed.
+For arithmetic computations, integers are used until some
+floating-point number is introduced, after which floating-point is used.
+For example,</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>5 / 4</tt></pre>
+</div></div>
+<div class="paragraph"><p>yields the result 1, while</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>5 / 4.0
+5 / ( [string length "abcd"] + 0.0 )</tt></pre>
+</div></div>
+<div class="paragraph"><p>both yield the result 1.25.</p></div>
+<div class="paragraph"><p>String values may be used as operands of the comparison operators,
+although the expression evaluator tries to do comparisons as integer
+or floating-point when it can.
+If one of the operands of a comparison is a string and the other
+has a numeric value, the numeric operand is converted back to
+a string using the C <em>sprintf</em> format specifier
+<em>%d</em> for integers and <em>%g</em> for floating-point values.
+For example, the expressions</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>"0x03" &gt; "2"
+"0y" &lt; "0x12"</tt></pre>
+</div></div>
+<div class="paragraph"><p>both evaluate to 1.  The first comparison is done using integer
+comparison, and the second is done using string comparison after
+the second operand is converted to the string <em>18</em>.</p></div>
+<div class="paragraph"><p>In general it is safest to enclose an expression in braces when
+entering it in a command:  otherwise, if the expression contains
+any white space then the Tcl interpreter will split it
+among several arguments.  For example, the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>expr $a + $b</tt></pre>
+</div></div>
+<div class="paragraph"><p>results in three arguments being passed to <a href="#_expr"><strong><tt>expr</tt></strong></a>:  <tt>$a</tt>,
++, and <tt>$b</tt>.  In addition, if the expression isn&#8217;t in braces
+then the Tcl interpreter will perform variable and command substitution
+immediately (it will happen in the command parser rather than in
+the expression parser).  In many cases the expression is being
+passed to a command that will evaluate the expression later (or
+even many times if, for example, the expression is to be used to
+decide when to exit a loop).  Usually the desired goal is to re-do
+the variable or command substitutions each time the expression is
+evaluated, rather than once and for all at the beginning.  For example,
+the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>for {set i 1} $i&lt;=10 {incr i} {...}        ** WRONG **</tt></pre>
+</div></div>
+<div class="paragraph"><p>is probably intended to iterate over all values of <tt>i</tt> from 1 to 10.
+After each iteration of the body of the loop, <a href="#_for"><strong><tt>for</tt></strong></a> will pass
+its second argument to the expression evaluator to see whether or not
+to continue processing.  Unfortunately, in this case the value of <tt>i</tt>
+in the second argument will be substituted once and for all when the
+<a href="#_for"><strong><tt>for</tt></strong></a> command is parsed.  If <tt>i</tt> was 0 before the <a href="#_for"><strong><tt>for</tt></strong></a>
+command was invoked then the second argument of <a href="#_for"><strong><tt>for</tt></strong></a> will be <tt>0&lt;=10</tt>
+which will always evaluate to 1, even though <tt>i</tt> eventually
+becomes greater than 10.  In the above case the loop will never
+terminate.  Instead, the expression should be placed in braces:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>for {set i 1} {$i&lt;=10} {incr i} {...}      ** RIGHT **</tt></pre>
+</div></div>
+<div class="paragraph"><p>This causes the substitution of <em>i</em>
+to be delayed; it will be re-done each time the expression is
+evaluated, which is the desired result.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_lists">LISTS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The third major way that strings are interpreted in Tcl is as lists.
+A list is just a string with a list-like structure
+consisting of fields separated by white space.  For example, the
+string</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>Al Sue Anne John</tt></pre>
+</div></div>
+<div class="paragraph"><p>is a list with four elements or fields.
+Lists have the same basic structure as command strings, except
+that a newline character in a list is treated as a field separator
+just like space or tab.  Conventions for braces and quotes
+and backslashes are the same for lists as for commands.  For example,
+the string</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>a b\ c {d e {f g h}}</tt></pre>
+</div></div>
+<div class="paragraph"><p>is a list with three elements:  <tt>a</tt>, <tt>b c</tt>, and <tt>d e {f g h}</tt>.</p></div>
+<div class="paragraph"><p>Whenever an element is extracted from a list, the same rules about
+braces and quotes and backslashes are applied as for commands.  Thus in
+the example above when the third element is extracted from the list,
+the result is</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>d e {f g h}</tt></pre>
+</div></div>
+<div class="paragraph"><p>(when the field was extracted, all that happened was to strip off
+the outermost layer of braces).  Command substitution and
+variable substitution are never
+made on a list (at least, not by the list-processing commands; the
+list can always be passed to the Tcl interpreter for evaluation).</p></div>
+<div class="paragraph"><p>The Tcl commands <a href="#_concat"><strong><tt>concat</tt></strong></a>, <a href="#_foreach"><strong><tt>foreach</tt></strong></a>, <a href="#_lappend"><strong><tt>lappend</tt></strong></a>, <a href="#_lindex"><strong><tt>lindex</tt></strong></a>, <a href="#_linsert"><strong><tt>linsert</tt></strong></a>,
+<a href="#_list"><strong><tt>list</tt></strong></a>, <a href="#_llength"><strong><tt>llength</tt></strong></a>, <a href="#_lrange"><strong><tt>lrange</tt></strong></a>, <a href="#_lreplace"><strong><tt>lreplace</tt></strong></a>, <a href="#_lsearch"><strong><tt>lsearch</tt></strong></a>, and <a href="#_lsort"><strong><tt>lsort</tt></strong></a> allow
+you to build lists, extract elements from them, search them, and perform
+other list-related functions.</p></div>
+<div class="paragraph"><p>Advanced list commands include <a href="#_lrepeat"><strong><tt>lrepeat</tt></strong></a>, <a href="#_lreverse"><strong><tt>lreverse</tt></strong></a>, <a href="#_lmap"><strong><tt>lmap</tt></strong></a>, <a href="#_lassign"><strong><tt>lassign</tt></strong></a>, <a href="#_lset"><strong><tt>lset</tt></strong></a>.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_list_expansion">LIST EXPANSION</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>A new addition to Tcl 8.5 is the ability to expand a list into separate
+arguments. Support for this feature is also available in Jim.</p></div>
+<div class="paragraph"><p>Consider the following attempt to exec a list:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set cmd {ls -l}
+exec $cmd</tt></pre>
+</div></div>
+<div class="paragraph"><p>This will attempt to exec the a command named "ls -l", which will clearly not
+work. Typically eval and concat are required to solve this problem, however
+it can be solved much more easily with <tt>{*}</tt>.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>exec {*}$cmd</tt></pre>
+</div></div>
+<div class="paragraph"><p>This will expand the following argument into individual elements and then evaluate
+the resulting command.</p></div>
+<div class="paragraph"><p>Note that the official Tcl syntax is <tt>{*}</tt>, however <tt>{expand}</tt> is retained
+for backward compatibility with experimental versions of this feature.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_regular_expressions">REGULAR EXPRESSIONS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Tcl provides two commands that support string matching using regular
+expressions, <a href="#_regexp"><strong><tt>regexp</tt></strong></a> and <a href="#_regsub"><strong><tt>regsub</tt></strong></a>, as well as <a href="#_switch"><strong><tt>switch</tt></strong></a> <tt>-regexp</tt> and
+<a href="#_lsearch"><strong><tt>lsearch</tt></strong></a> <tt>-regexp</tt>.</p></div>
+<div class="paragraph"><p>Regular expressions may be implemented one of two ways. Either using the system&#8217;s C library
+POSIX regular expression support, or using the built-in regular expression engine.
+The differences between these are described below.</p></div>
+<div class="paragraph"><p><strong>NOTE</strong> Tcl 7.x and 8.x use perl-style Advanced Regular Expressions (<tt>ARE</tt>).</p></div>
+<div class="sect2">
+<h3 id="_posix_regular_expressions">POSIX Regular Expressions</h3>
+<div class="paragraph"><p>If the system supports POSIX regular expressions, and UTF-8 support is not enabled,
+this support will be used by default. The type of regular expressions supported are
+Extended Regular Expressions (<tt>ERE</tt>) rather than Basic Regular Expressions (<tt>BRE</tt>).
+See REG_EXTENDED in the documentation.</p></div>
+<div class="paragraph"><p>Using the system-supported POSIX regular expressions will typically
+make for the smallest code size, but some features such as UTF-8
+and <tt>\w</tt>, <tt>\d</tt>, <tt>\s</tt> are not supported.</p></div>
+<div class="paragraph"><p>See regex(3) and regex(7) for full details.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_jim_built_in_regular_expressions">Jim built-in Regular Expressions</h3>
+<div class="paragraph"><p>The Jim built-in regulare expression engine may be selected with <tt>./configure --with-jim-regexp</tt>
+or it will be selected automatically if UTF-8 support is enabled.</p></div>
+<div class="paragraph"><p>This engine supports UTF-8 as well as some <tt>ARE</tt> features. The differences with both Tcl 7.x/8.x
+and POSIX are highlighted below.</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+UTF-8 strings and patterns are both supported
+</p>
+</li>
+<li>
+<p>
+Supported character classes: <tt>[:alnum:]</tt>, <tt>[:digit:]</tt> and <tt>[:space:]</tt>
+</p>
+</li>
+<li>
+<p>
+Supported shorthand character classes: <tt>\w</tt> = <tt>[:alnum:]</tt>, <tt>\d</tt> = <tt>[:digit:],</tt> <tt>\s</tt> = <tt>[:space:]</tt>
+</p>
+</li>
+<li>
+<p>
+Character classes apply to ASCII characters only
+</p>
+</li>
+<li>
+<p>
+Supported constraint escapes: <tt>\m</tt> = <tt>\&lt;</tt> = start of word, <tt>\M</tt> = <tt>\&gt;</tt> = end of word
+</p>
+</li>
+<li>
+<p>
+Backslash escapes may be used within regular expressions, such as <tt>\n</tt> = newline, <tt>\uNNNN</tt> = unicode
+</p>
+</li>
+<li>
+<p>
+Support for the <tt>?</tt> non-greedy quantifier. e.g. <tt>*?</tt>
+</p>
+</li>
+<li>
+<p>
+Support for non-capuring parentheses <tt>(?:&#8230;)</tt>
+</p>
+</li>
+</ol></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_command_results">COMMAND RESULTS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Each command produces two results:  a code and a string.  The
+code indicates whether the command completed successfully or not,
+and the string gives additional information.  The valid codes are
+defined in jim.h, and are:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>JIM_OK(0)</tt>
+</dt>
+<dd>
+<p>
+    This is the normal return code, and indicates that the command completed
+    successfully.  The string gives the command&#8217;s return value.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>JIM_ERR(1)</tt>
+</dt>
+<dd>
+<p>
+    Indicates that an error occurred; the string gives a message describing
+    the error.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>JIM_RETURN(2)</tt>
+</dt>
+<dd>
+<p>
+    Indicates that the <a href="#_return"><strong><tt>return</tt></strong></a> command has been invoked, and that the
+    current procedure (or top-level command or <a href="#_source"><strong><tt>source</tt></strong></a> command)
+    should return immediately.  The
+    string gives the return value for the procedure or command.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>JIM_BREAK(3)</tt>
+</dt>
+<dd>
+<p>
+    Indicates that the <a href="#_break"><strong><tt>break</tt></strong></a> command has been invoked, so the
+    innermost loop should abort immediately.  The string should always
+    be empty.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>JIM_CONTINUE(4)</tt>
+</dt>
+<dd>
+<p>
+    Indicates that the <a href="#_continue"><strong><tt>continue</tt></strong></a> command has been invoked, so the
+    innermost loop should go on to the next iteration.  The string
+    should always be empty.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>JIM_SIGNAL(5)</tt>
+</dt>
+<dd>
+<p>
+    Indicates that a signal was caught while executing a commands.
+    The string contains the name of the signal caught.
+    See the <a href="#_signal"><strong><tt>signal</tt></strong></a> and <a href="#_catch"><strong><tt>catch</tt></strong></a> commands.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>JIM_EXIT(6)</tt>
+</dt>
+<dd>
+<p>
+    Indicates that the command called the <a href="#_exit"><strong><tt>exit</tt></strong></a> command.
+    The string contains the exit code.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>Tcl programmers do not normally need to think about return codes,
+since <tt>JIM_OK</tt> is almost always returned.  If anything else is returned
+by a command, then the Tcl interpreter immediately stops processing
+commands and returns to its caller.  If there are several nested
+invocations of the Tcl interpreter in progress, then each nested
+command will usually return the error to its caller, until eventually
+the error is reported to the top-level application code.  The
+application will then display the error message for the user.</p></div>
+<div class="paragraph"><p>In a few cases, some commands will handle certain <a href="#_error"><strong><tt>error</tt></strong></a> conditions
+themselves and not return them upwards.  For example, the <a href="#_for"><strong><tt>for</tt></strong></a>
+command checks for the <tt>JIM_BREAK</tt> code; if it occurs, then <a href="#_for"><strong><tt>for</tt></strong></a>
+stops executing the body of the loop and returns <tt>JIM_OK</tt> to its
+caller.  The <a href="#_for"><strong><tt>for</tt></strong></a> command also handles <tt>JIM_CONTINUE</tt> codes and the
+procedure interpreter handles <tt>JIM_RETURN</tt> codes.  The <a href="#_catch"><strong><tt>catch</tt></strong></a>
+command allows Tcl programs to catch errors and handle them without
+aborting command interpretation any further.</p></div>
+<div class="paragraph"><p>The <a href="#_info"><strong><tt>info</tt></strong></a> <tt>returncodes</tt> command may be used to programmatically map between
+return codes and names.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_procedures">PROCEDURES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Tcl allows you to extend the command interface by defining
+procedures.  A Tcl procedure can be invoked just like any other Tcl
+command (it has a name and it receives one or more arguments).
+The only difference is that its body isn&#8217;t a piece of C code linked
+into the program; it is a string containing one or more other
+Tcl commands.</p></div>
+<div class="paragraph"><p>The <a href="#_proc"><strong><tt>proc</tt></strong></a> command is used to create a new Tcl command procedure:</p></div>
+<div class="paragraph"><p><tt><strong>proc</strong> <em>name arglist ?statics? body</em></tt></p></div>
+<div class="paragraph"><p>The new command is named <tt><em>name</em></tt>, and it replaces any existing command
+there may have been by that name. Whenever the new command is
+invoked, the contents of <tt><em>body</em></tt> will be executed by the Tcl
+interpreter.</p></div>
+<div class="paragraph"><p><tt><em>arglist</em></tt> specifies the formal arguments to the procedure.
+It consists of a list, possibly empty, of the following
+argument specifiers:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>name</tt>
+</dt>
+<dd>
+<p>
+    Required Argument - A simple argument name.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>name default</tt>
+</dt>
+<dd>
+<p>
+    Optional Argument - A two-element list consisting of the
+    argument name, followed by the default value, which will
+    be used if the corresponding argument is not supplied.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&amp;name</tt>
+</dt>
+<dd>
+<p>
+    Reference Argument - The caller is expected to pass the name of
+    an existing variable. An implicit <a href="#_upvar"><strong><tt>upvar</tt></strong></a> <tt>1 'origname' 'name'</tt> is done
+    to make the variable available in the proc scope.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>args</strong></tt>
+</dt>
+<dd>
+<p>
+    Variable Argument - The special name <tt><em>args</em></tt>, which is
+    assigned all remaining arguments (including none) as a list. The
+    variable argument may only be specified once. Note that
+    the syntax <tt>args newname</tt> may be used to retain the special
+    behaviour of <tt><em>args</em></tt> with a different local name. In this case,
+    the variable is named <tt><em>newname</em></tt> rather than <tt><em>args</em></tt>.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>When the command is invoked, a local variable will be created for each of
+the formal arguments to the procedure; its value will be the value
+of corresponding argument in the invoking command or the argument&#8217;s
+default value.</p></div>
+<div class="paragraph"><p>Arguments with default values need not be specified in a procedure
+invocation.  However, there must be enough actual arguments for all
+required arguments, and there must not be any extra actual arguments
+(unless the Variable Argument is specified).</p></div>
+<div class="paragraph"><p>Actual arguments are assigned to formal arguments as in left-to-right
+order with the following precedence.</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Required Arguments (including Reference Arguments)
+</p>
+</li>
+<li>
+<p>
+Optional Arguments
+</p>
+</li>
+<li>
+<p>
+Variable Argument
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>The following example illustrates precedence. Assume a procedure declaration:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>proc p {{a A} args b {c C} d} {...}</tt></pre>
+</div></div>
+<div class="paragraph"><p>This procedure requires at least two arguments, but can accept an unlimited number.
+The following table shows how various numbers of arguments are assigned.
+Values marked as <tt>-</tt> are assigned the default value.</p></div>
+<div class="tableblock">
+<table rules="all"
+width="40%"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="16%" />
+<col width="16%" />
+<col width="16%" />
+<col width="16%" />
+<col width="16%" />
+<col width="16%" />
+<thead>
+<tr>
+<th align="left" valign="top">Number of arguments</th>
+<th align="left" valign="top">a</th>
+<th align="left" valign="top">args</th>
+<th align="left" valign="top">b</th>
+<th align="left" valign="top">c</th>
+<th align="left" valign="top">d</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table">2</p></td>
+<td align="left" valign="top"><p class="table">-</p></td>
+<td align="left" valign="top"><p class="table">-</p></td>
+<td align="left" valign="top"><p class="table">1</p></td>
+<td align="left" valign="top"><p class="table">-</p></td>
+<td align="left" valign="top"><p class="table">2</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table">3</p></td>
+<td align="left" valign="top"><p class="table">1</p></td>
+<td align="left" valign="top"><p class="table">-</p></td>
+<td align="left" valign="top"><p class="table">2</p></td>
+<td align="left" valign="top"><p class="table">-</p></td>
+<td align="left" valign="top"><p class="table">3</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table">4</p></td>
+<td align="left" valign="top"><p class="table">1</p></td>
+<td align="left" valign="top"><p class="table">-</p></td>
+<td align="left" valign="top"><p class="table">2</p></td>
+<td align="left" valign="top"><p class="table">3</p></td>
+<td align="left" valign="top"><p class="table">4</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table">5</p></td>
+<td align="left" valign="top"><p class="table">1</p></td>
+<td align="left" valign="top"><p class="table">2</p></td>
+<td align="left" valign="top"><p class="table">3</p></td>
+<td align="left" valign="top"><p class="table">4</p></td>
+<td align="left" valign="top"><p class="table">5</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table">6</p></td>
+<td align="left" valign="top"><p class="table">1</p></td>
+<td align="left" valign="top"><p class="table">2,3</p></td>
+<td align="left" valign="top"><p class="table">4</p></td>
+<td align="left" valign="top"><p class="table">5</p></td>
+<td align="left" valign="top"><p class="table">6</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="paragraph"><p>When <tt><em>body</em></tt> is being executed, variable names normally refer to local
+variables, which are created automatically when referenced and deleted
+when the procedure returns.  One local variable is automatically created
+for each of the procedure&#8217;s arguments.  Global variables can be
+accessed by invoking the <a href="#_global"><strong><tt>global</tt></strong></a> command or via the <tt>::</tt> prefix.</p></div>
+<div class="sect2">
+<h3 id="_new_in_jim">New in Jim</h3>
+<div class="paragraph"><p>In addition to procedure arguments, Jim procedures may declare static variables.
+These variables scoped to the procedure and initialised at procedure definition.
+Either from the static variable definition, or from the enclosing scope.</p></div>
+<div class="paragraph"><p>Consider the following example:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; set a 1
+jim&gt; proc a {} {a {b 2}} {
+    set c 1
+    puts "$a $b $c"
+    incr a
+    incr b
+    incr c
+}
+jim&gt; a
+1 2 1
+jim&gt; a
+2 3 1</tt></pre>
+</div></div>
+<div class="paragraph"><p>The static variable <tt><em>a</em></tt> has no initialiser, so it is initialised from
+the enclosing scope with the value 1. (Note that it is an error if there
+is no variable with the same name in the enclosing scope). However <tt><em>b</em></tt>
+has an initialiser, so it is initialised to 2.</p></div>
+<div class="paragraph"><p>Unlike a local variable, the value of a static variable is retained across
+invocations of the procedure.</p></div>
+<div class="paragraph"><p>See the <a href="#_proc"><strong><tt>proc</tt></strong></a> command for information on how to define procedures
+and what happens when they are invoked. See also NAMESPACES.</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_variables_scalars_and_arrays">VARIABLES - SCALARS AND ARRAYS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Tcl allows the definition of variables and the use of their values
+either through <em>$</em>-style variable substitution, the <a href="#_set"><strong><tt>set</tt></strong></a>
+command, or a few other mechanisms.</p></div>
+<div class="paragraph"><p>Variables need not be declared:  a new variable will automatically
+be created each time a new variable name is used.</p></div>
+<div class="paragraph"><p>Tcl supports two types of variables:  scalars and arrays.
+A scalar variable has a single value, whereas an array variable
+can have any number of elements, each with a name (called
+its <em>index</em>) and a value.</p></div>
+<div class="paragraph"><p>Array indexes may be arbitrary strings; they need not be numeric.
+Parentheses are used refer to array elements in Tcl commands.
+For example, the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set x(first) 44</tt></pre>
+</div></div>
+<div class="paragraph"><p>will modify the element of <em>x</em> whose index is <em>first</em>
+so that its new value is <em>44</em>.</p></div>
+<div class="paragraph"><p>Two-dimensional arrays can be simulated in Tcl by using indexes
+that contain multiple concatenated values.
+For example, the commands</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a(2,3) 1
+set a(3,6) 2</tt></pre>
+</div></div>
+<div class="paragraph"><p>set the elements of <em>a</em> whose indexes are <em>2,3</em> and <em>3,6</em>.</p></div>
+<div class="paragraph"><p>In general, array elements may be used anywhere in Tcl that scalar
+variables may be used.</p></div>
+<div class="paragraph"><p>If an array is defined with a particular name, then there may
+not be a scalar variable with the same name.</p></div>
+<div class="paragraph"><p>Similarly, if there is a scalar variable with a particular
+name then it is not possible to make array references to the
+variable.</p></div>
+<div class="paragraph"><p>To convert a scalar variable to an array or vice versa, remove
+the existing variable with the <a href="#_unset"><strong><tt>unset</tt></strong></a> command.</p></div>
+<div class="paragraph"><p>The <a href="#_array"><strong><tt>array</tt></strong></a> command provides several features for dealing
+with arrays, such as querying the names of all the elements of
+the array and converting between an array and a list.</p></div>
+<div class="paragraph"><p>Variables may be either global or local.  If a variable
+name is used when a procedure isn&#8217;t being executed, then it
+automatically refers to a global variable.  Variable names used
+within a procedure normally refer to local variables associated with that
+invocation of the procedure.  Local variables are deleted whenever
+a procedure exits.  Either <a href="#_global"><strong><tt>global</tt></strong></a> command may be used to request
+that a name refer to a global variable for the duration of the current
+procedure (this is somewhat analogous to <em>extern</em> in C), or the variable
+may be explicitly scoped with the <tt>::</tt> prefix. For example</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a 1
+set b 2
+proc p {} {
+    set c 3
+    global a</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>    puts "$a $::b $c"
+}
+p</tt></pre>
+</div></div>
+<div class="paragraph"><p>will output:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>1 2 3</tt></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_arrays_as_lists_in_jim">ARRAYS AS LISTS IN JIM</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Unlike Tcl, Jim can automatically convert between a list (with an even
+number of elements) and an array value. This is similar to the way Tcl
+can convert between a string and a list.</p></div>
+<div class="paragraph"><p>For example:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a {1 one 2 two}
+puts $a(2)</tt></pre>
+</div></div>
+<div class="paragraph"><p>will output:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>two</tt></pre>
+</div></div>
+<div class="paragraph"><p>Thus <a href="#_array"><strong><tt>array</tt></strong></a> <tt>set</tt> is equivalent to <a href="#_set"><strong><tt>set</tt></strong></a> when the variable does not
+exist or is empty.</p></div>
+<div class="paragraph"><p>The reverse is also true where an array will be converted into
+a list.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a(1) one; set a(2) two
+puts $a</tt></pre>
+</div></div>
+<div class="paragraph"><p>will output:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>1 one 2 two</tt></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_dictionary_values">DICTIONARY VALUES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Tcl 8.5 introduced the dict command, and Jim Tcl has added a version
+of this command. Dictionaries provide efficient access to key-value
+pairs, just like arrays, but dictionaries are pure values. This
+means that you can pass them to a procedure just as a list or a
+string. Tcl dictionaries are therefore much more like Tcl lists,
+except that they represent a mapping from keys to values, rather
+than an ordered sequence.</p></div>
+<div class="paragraph"><p>You can nest dictionaries, so that the value for a particular key
+consists of another dictionary. That way you can elegantly build
+complicated data structures, such as hierarchical databases. You
+can also combine dictionaries with other Tcl data structures. For
+instance, you can build a list of dictionaries that themselves
+contain lists.</p></div>
+<div class="paragraph"><p>Dictionaries are values that contain an efficient, order-preserving
+mapping from arbitrary keys to arbitrary values. Each key in the
+dictionary maps to a single value. They have a textual format that
+is exactly that of any list with an even number of elements, with
+each mapping in the dictionary being represented as two items in
+the list. When a command takes a dictionary and produces a new
+dictionary based on it (either returning it or writing it back into
+the variable that the starting dictionary was read from) the new
+dictionary will have the same order of keys, modulo any deleted
+keys and with new keys added on to the end. When a string is
+interpreted as a dictionary and it would otherwise have duplicate
+keys, only the last value for a particular key is used; the others
+are ignored, meaning that, "apple banana" and "apple carrot apple
+banana" are equivalent dictionaries (with different string
+representations).</p></div>
+<div class="paragraph"><p>Note that in Jim, arrays are implemented as dictionaries.
+Thus automatic conversion between lists and dictionaries applies
+as it does for arrays.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; dict set a 1 one
+1 one
+jim&gt; dict set a 2 two
+1 one 2 two
+jim&gt; puts $a
+1 one 2 two
+jim&gt; puts $a(2)
+two
+jim&gt; dict set a 3 T three
+1 one 2 two 3 {T three}</tt></pre>
+</div></div>
+<div class="paragraph"><p>See the <a href="#_dict"><strong><tt>dict</tt></strong></a> command for more details.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_namespaces">NAMESPACES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Tcl added namespaces as a mechanism avoiding name clashes, especially in applications
+including a number of 3rd party components. While there is less need for namespaces
+in Jim Tcl (which does not strive to support large applications), it is convenient to
+provide a subset of the support for namespaces to easy porting code from Tcl.</p></div>
+<div class="paragraph"><p>Jim Tcl currently supports "light-weight" namespaces which should be adequate for most
+purposes. This feature is currently experimental. See README.namespaces for more information
+and the documentation of the <a href="#_namespace"><strong><tt>namespace</tt></strong></a> command.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_garbage_collection_references_lambda">GARBAGE COLLECTION, REFERENCES, LAMBDA</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Unlike Tcl, Jim has some sophisticated support for functional programming.
+These are described briefly below.</p></div>
+<div class="paragraph"><p>More information may be found at <a href="http://wiki.tcl.tk/13847">http://wiki.tcl.tk/13847</a></p></div>
+<div class="sect2">
+<h3 id="_references">References</h3>
+<div class="paragraph"><p>A reference can be thought of as holding a value with one level of indirection,
+where the value may be garbage collected when unreferenced.
+Consider the following example:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; set r [ref "One String" test]
+&lt;reference.&lt;test___&gt;.00000000000000000000&gt;
+jim&gt; getref $r
+One String</tt></pre>
+</div></div>
+<div class="paragraph"><p>The operation <a href="#_ref"><strong><tt>ref</tt></strong></a> creates a references to the value specified by the
+first argument. (The second argument is a "type" used for documentation purposes).</p></div>
+<div class="paragraph"><p>The operation <a href="#_getref"><strong><tt>getref</tt></strong></a> is the dereferencing operation which retrieves the value
+stored in the reference.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; setref $r "New String"
+New String
+jim&gt; getref $r
+New String</tt></pre>
+</div></div>
+<div class="paragraph"><p>The operation <a href="#_setref"><strong><tt>setref</tt></strong></a> replaces the value stored by the reference. If the old value
+is no longer accessible by any reference, it will eventually be automatically be garbage
+collected.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_garbage_collection">Garbage Collection</h3>
+<div class="paragraph"><p>Normally, all values in Tcl are passed by value. As such values are copied and released
+automatically as necessary.</p></div>
+<div class="paragraph"><p>With the introduction of references, it is possible to create values whose lifetime
+transcend their scope. To support this, case, the Jim system will periodically identify
+and discard objects which are no longer accessible by any reference.</p></div>
+<div class="paragraph"><p>The <a href="#_collect"><strong><tt>collect</tt></strong></a> command may be used to force garbage collection.  Consider a reference created
+with a finalizer:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; proc f {ref value} { puts "Finaliser called for $ref,$value" }
+jim&gt; set r [ref "One String" test f]
+&lt;reference.&lt;test___&gt;.00000000000
+jim&gt; collect
+0
+jim&gt; set r ""
+jim&gt; collect
+Finaliser called for &lt;reference.&lt;test___&gt;.00000000000,One String
+1</tt></pre>
+</div></div>
+<div class="paragraph"><p>Note that once the reference, <em>r</em>, was modified so that it no longer
+contained a reference to the value, the garbage collector discarded
+the value (after calling the finalizer).</p></div>
+<div class="paragraph"><p>The finalizer for a reference may be examined or changed with the <a href="#_finalize"><strong><tt>finalize</tt></strong></a> command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; finalize $r
+f
+jim&gt; finalize $r newf
+newf</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_lambda">Lambda</h3>
+<div class="paragraph"><p>Jim provides a garbage collected lambda function. This is a procedure
+which is able to create an anonymous procedure.  Consider:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; set f [lambda {a} {{x 0}} { incr x $a }]
+jim&gt; $f 1
+1
+jim&gt; $f 2
+3
+jim&gt; set f ""</tt></pre>
+</div></div>
+<div class="paragraph"><p>This create an anonymous procedure (with the name stored in <em>f</em>), with a static variable
+which is incremented by the supplied value and the result returned.</p></div>
+<div class="paragraph"><p>Once the procedure name is no longer accessible, it will automatically be deleted
+when the garbage collector runs.</p></div>
+<div class="paragraph"><p>The procedure may also be delete immediately by renaming it "". e.g.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; rename $f ""</tt></pre>
+</div></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_utf_8_and_unicode">UTF-8 AND UNICODE</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>If Jim is built with UTF-8 support enabled (configure --enable-utf),
+then most string-related commands become UTF-8 aware.  These include,
+but are not limited to, <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>, <a href="#_split"><strong><tt>split</tt></strong></a>, <a href="#_glob"><strong><tt>glob</tt></strong></a>, <a href="#_scan"><strong><tt>scan</tt></strong></a> and
+<a href="#_format"><strong><tt>format</tt></strong></a>.</p></div>
+<div class="paragraph"><p>UTF-8 encoding has many advantages, but one of the complications is that
+characters can take a variable number of bytes. Thus the addition of
+<a href="#_string"><strong><tt>string</tt></strong></a> <tt>bytelength</tt> which returns the number of bytes in a string,
+while <a href="#_string"><strong><tt>string</tt></strong></a> <tt>length</tt> returns the number of characters.</p></div>
+<div class="paragraph"><p>If UTF-8 support is not enabled, all commands treat bytes as characters
+and <a href="#_string"><strong><tt>string</tt></strong></a> <tt>bytelength</tt> returns the same value as <a href="#_string"><strong><tt>string</tt></strong></a> <tt>length</tt>.</p></div>
+<div class="paragraph"><p>Note that even if UTF-8 support is not enabled, the <tt>\uNNNN</tt> and related syntax
+is still available to embed UTF-8 sequences.</p></div>
+<div class="paragraph"><p>Jim Tcl supports all currently defined unicode codepoints. That is 21 bits, up to +<em>U+1FFFFF</em>.</p></div>
+<div class="sect2">
+<h3 id="_string_matching">String Matching</h3>
+<div class="paragraph"><p>Commands such as <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>, <a href="#_lsearch"><strong><tt>lsearch</tt></strong></a> <tt>-glob</tt>, <a href="#_array"><strong><tt>array</tt></strong></a> <tt>names</tt> and others use string
+pattern matching rules. These commands support UTF-8. For example:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>string match a\[\ua0-\ubf\]b "a\u00a3b"</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_format_and_scan">format and scan</h3>
+<div class="paragraph"><p><tt>format %c</tt> allows a unicode codepoint to be be encoded. For example, the following will return
+a string with two bytes and one character. The same as <tt>\ub5</tt></p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>format %c 0xb5</tt></pre>
+</div></div>
+<div class="paragraph"><p><a href="#_format"><strong><tt>format</tt></strong></a> respects widths as character widths, not byte widths. For example, the following will
+return a string with three characters, not three bytes.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>format %.3s \ub5\ub6\ub7\ub8</tt></pre>
+</div></div>
+<div class="paragraph"><p>Similarly, <tt>scan &#8230; %c</tt> allows a UTF-8 to be decoded to a unicode codepoint. The following will set
+<tt><em>a</em></tt> to 181 (0xb5) and <tt><em>b</em></tt> to 65 (0x41).</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>scan \u00b5A %c%c a b</tt></pre>
+</div></div>
+<div class="paragraph"><p><a href="#_scan"><strong><tt>scan</tt></strong></a> <tt>%s</tt> will also accept a character class, including unicode ranges.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_string_classes">String Classes</h3>
+<div class="paragraph"><p><a href="#_string"><strong><tt>string</tt></strong></a> <tt>is</tt> has <strong>not</strong> been extended to classify UTF-8 characters. Therefore, the following
+will return 0, even though the string may be considered to be alphabetic.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>string is alpha \ub5Test</tt></pre>
+</div></div>
+<div class="paragraph"><p>This does not affect the string classes <em>ascii</em>, <em>control</em>, <em>digit</em>, <em>double</em>, <em>integer</em> or <em>xdigit</em>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_case_mapping_and_conversion">Case Mapping and Conversion</h3>
+<div class="paragraph"><p>Jim provides a simplified unicode case mapping. This means that case conversion
+and comparison will not increase or decrease the number of characters in a string.
+(Although it may change the number of bytes).</p></div>
+<div class="paragraph"><p><a href="#_string"><strong><tt>string</tt></strong></a> <tt>toupper</tt> will convert any lowercase letters to their uppercase equivalent.
+Any character which is not a letter or has no uppercase equivalent is left unchanged.
+Similarly for <a href="#_string"><strong><tt>string</tt></strong></a> <tt>tolower</tt> and <a href="#_string"><strong><tt>string</tt></strong></a> <tt>totitle</tt>.</p></div>
+<div class="paragraph"><p>Commands which perform case insensitive matches, such as <a href="#_string"><strong><tt>string</tt></strong></a> <tt>compare -nocase</tt>
+and <a href="#_lsearch"><strong><tt>lsearch</tt></strong></a> <tt>-nocase</tt> fold both strings to uppercase before comparison.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_invalid_utf_8_sequences">Invalid UTF-8 Sequences</h3>
+<div class="paragraph"><p>Some UTF-8 character sequences are invalid, such as those beginning with <em>0xff</em>,
+those which represent character sequences longer than 3 bytes (greater than U+FFFF),
+and those which end prematurely, such as a lone <em>0xc2</em>.</p></div>
+<div class="paragraph"><p>In these situations, the offending bytes are treated as single characters. For example,
+the following returns 2.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>string bytelength \xff\xff</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_regular_expressions_2">Regular Expressions</h3>
+<div class="paragraph"><p>If UTF-8 support is enabled, the built-in regular expression engine will be
+selected which supports UTF-8 strings and patterns.</p></div>
+<div class="paragraph"><p>See REGULAR EXPRESSIONS</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_built_in_commands">BUILT-IN COMMANDS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The Tcl library provides the following built-in commands, which will
+be available in any application using Tcl.  In addition to these
+built-in commands, there may be additional commands defined by each
+application, plus commands defined as Tcl procedures.</p></div>
+<div class="paragraph"><p>In the command syntax descriptions below, words in <tt><strong>boldface</strong></tt> are
+literals that you type verbatim to Tcl.</p></div>
+<div class="paragraph"><p>Words in <tt><em>italics</em></tt> are meta-symbols; they serve as names for any of
+a range of values that you can type.</p></div>
+<div class="paragraph"><p>Optional arguments or groups of arguments are indicated by enclosing them
+in <tt>?question-marks?</tt>.</p></div>
+<div class="paragraph"><p>Ellipses (<tt>...</tt>) indicate that any number of additional
+arguments or groups of arguments may appear, in the same format
+as the preceding argument(s).</p></div>
+<div class="sect2">
+<h3 id="CommandIndex">Command Index</h3>
+<div class="tableblock">
+<table rules="none"
+width="100%"
+frame="void"
+cellspacing="0" cellpadding="4">
+<col width="12%" />
+<col width="12%" />
+<col width="12%" />
+<col width="12%" />
+<col width="12%" />
+<col width="12%" />
+<col width="12%" />
+<col width="12%" />
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#cmd_2"><strong><tt>after</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_aio"><strong><tt>aio</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_alarm"><strong><tt>alarm</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_alias"><strong><tt>alias</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_append"><strong><tt>append</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_apply"><strong><tt>apply</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_array"><strong><tt>array</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_binary"><strong><tt>binary</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_break"><strong><tt>break</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_case"><strong><tt>case</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_catch"><strong><tt>catch</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_cd"><strong><tt>cd</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_4"><strong><tt>class</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_clock"><strong><tt>clock</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_close"><strong><tt>close</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_collect"><strong><tt>collect</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_concat"><strong><tt>concat</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_continue"><strong><tt>continue</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_curry"><strong><tt>curry</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_dict"><strong><tt>dict</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_env"><strong><tt>env</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_eof"><strong><tt>eof</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_error"><strong><tt>error</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_eval"><strong><tt>eval</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#cmd_2"><strong><tt>eventloop</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_exec"><strong><tt>exec</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_exists"><strong><tt>exists</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_exit"><strong><tt>exit</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_expr"><strong><tt>expr</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_fconfigure"><strong><tt>fconfigure</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_file"><strong><tt>file</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_finalize"><strong><tt>finalize</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_flush"><strong><tt>flush</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_for"><strong><tt>for</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_foreach"><strong><tt>foreach</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_format"><strong><tt>format</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_getref"><strong><tt>getref</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_gets"><strong><tt>gets</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_glob"><strong><tt>glob</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_global"><strong><tt>global</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_history"><strong><tt>history</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_if"><strong><tt>if</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_incr"><strong><tt>incr</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_info"><strong><tt>info</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_join"><strong><tt>join</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_kill"><strong><tt>kill</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lambda"><strong><tt>lambda</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lappend"><strong><tt>lappend</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_lassign"><strong><tt>lassign</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lindex"><strong><tt>lindex</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_linsert"><strong><tt>linsert</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_list"><strong><tt>list</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_llength"><strong><tt>llength</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lmap"><strong><tt>lmap</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_load"><strong><tt>load</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_local"><strong><tt>local</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_loop"><strong><tt>loop</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lrange"><strong><tt>lrange</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lrepeat"><strong><tt>lrepeat</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lreplace"><strong><tt>lreplace</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lreverse"><strong><tt>lreverse</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lsearch"><strong><tt>lsearch</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lset"><strong><tt>lset</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_lsort"><strong><tt>lsort</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_namespace"><strong><tt>namespace</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_4"><strong><tt>oo</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_open"><strong><tt>open</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_1"><strong><tt>os.fork</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_1"><strong><tt>os.gethostname</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_1"><strong><tt>os.getids</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_1"><strong><tt>os.uptime</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_1"><strong><tt>os.wait</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#cmd_3"><strong><tt>pack</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_3"><strong><tt>pack</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_package"><strong><tt>package</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_pid"><strong><tt>pid</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_1"><strong><tt>posix</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_proc"><strong><tt>proc</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_puts"><strong><tt>puts</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_pwd"><strong><tt>pwd</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_rand"><strong><tt>rand</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_range"><strong><tt>range</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_read"><strong><tt>read</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_ref"><strong><tt>ref</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_regexp"><strong><tt>regexp</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_regsub"><strong><tt>regsub</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_rename"><strong><tt>rename</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_return"><strong><tt>return</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_scan"><strong><tt>scan</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_seek"><strong><tt>seek</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_set"><strong><tt>set</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_setref"><strong><tt>setref</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_signal"><strong><tt>signal</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_sleep"><strong><tt>sleep</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_socket"><strong><tt>socket</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_source"><strong><tt>source</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_split"><strong><tt>split</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_stackdump"><strong><tt>stackdump</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_stacktrace"><strong><tt>stacktrace</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_string"><strong><tt>string</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_subst"><strong><tt>subst</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_4"><strong><tt>super</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_switch"><strong><tt>switch</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_syslog"><strong><tt>syslog</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#_tailcall"><strong><tt>tailcall</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_tcl_prefix"><strong><tt>tcl::prefix</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_tell"><strong><tt>tell</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_throw"><strong><tt>throw</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_time"><strong><tt>time</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_tree"><strong><tt>tree</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_try"><strong><tt>try</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_unknown"><strong><tt>unknown</tt></strong></a></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#cmd_3"><strong><tt>unpack</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_unset"><strong><tt>unset</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_upcall"><strong><tt>upcall</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_2"><strong><tt>update</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_uplevel"><strong><tt>uplevel</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_upvar"><strong><tt>upvar</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#cmd_2"><strong><tt>vwait</tt></strong></a></p></td>
+<td align="left" valign="top"><p class="table"><a href="#_while"><strong><tt>while</tt></strong></a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_alarm">alarm</h3>
+<div class="paragraph"><p><tt><strong>alarm</strong> <em>seconds</em></tt></p></div>
+<div class="paragraph"><p>Delivers the <tt>SIGALRM</tt> signal to the process after the given
+number of seconds. If the platform supports <em>ualarm(3)</em> then
+the argument may be a floating point value. Otherwise it must
+be an integer.</p></div>
+<div class="paragraph"><p>Note that unless a signal handler for <tt>SIGALRM</tt> has been installed
+(see <a href="#_signal"><strong><tt>signal</tt></strong></a>), the process will exit on this signal.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_alias">alias</h3>
+<div class="paragraph"><p><tt><strong>alias</strong> <em>name args...</em></tt></p></div>
+<div class="paragraph"><p>Creates a single word alias (command) for one or more words. For example,
+the following creates an alias for the command <a href="#_info"><strong><tt>info</tt></strong></a> <tt>exists</tt>.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>alias e info exists
+if {[e var]} {
+  ...
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p><a href="#_alias"><strong><tt>alias</tt></strong></a> returns <tt><em>name</em></tt>, allowing it to be used with <a href="#_local"><strong><tt>local</tt></strong></a>.</p></div>
+<div class="paragraph"><p>See also <a href="#_proc"><strong><tt>proc</tt></strong></a>, <a href="#_curry"><strong><tt>curry</tt></strong></a>, <a href="#_lambda"><strong><tt>lambda</tt></strong></a>, <a href="#_local"><strong><tt>local</tt></strong></a>, <a href="#_info"><strong><tt>info</tt></strong></a> <tt>alias</tt>, <a href="#_exists"><strong><tt>exists</tt></strong></a> <tt>-alias</tt></p></div>
+</div>
+<div class="sect2">
+<h3 id="_append">append</h3>
+<div class="paragraph"><p><tt><strong>append</strong> <em>varName value ?value value &#8230;?</em></tt></p></div>
+<div class="paragraph"><p>Append all of the <tt><em>value</em></tt> arguments to the current value
+of variable <tt><em>varName</em></tt>.  If <tt><em>varName</em></tt> doesn&#8217;t exist,
+it is given a value equal to the concatenation of all the
+<tt><em>value</em></tt> arguments.</p></div>
+<div class="paragraph"><p>This command provides an efficient way to build up long
+variables incrementally.
+For example, "<a href="#_append"><strong><tt>append</tt></strong></a> <tt>a $b</tt>" is much more efficient than
+"<a href="#_set"><strong><tt>set</tt></strong></a> <tt>a $a$b</tt>" if <tt>$a</tt> is long.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_apply">apply</h3>
+<div class="paragraph"><p><tt><strong>apply</strong> <em>lambdaExpr ?arg1 arg2 ...?</em></tt></p></div>
+<div class="paragraph"><p>The command <a href="#_apply"><strong><tt>apply</tt></strong></a> provides for anonymous procedure calls,
+similar to <a href="#_lambda"><strong><tt>lambda</tt></strong></a>, but without command name being created, even temporarily.</p></div>
+<div class="paragraph"><p>The function  <tt><em>lambdaExpr</em></tt> is a two element list <tt>{args body}</tt>
+or a three element list <tt>{args body namespace}</tt>. The first element
+args specifies the formal arguments, in the same form as the <a href="#_proc"><strong><tt>proc</tt></strong></a> and <a href="#_lambda"><strong><tt>lambda</tt></strong></a> commands.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_array">array</h3>
+<div class="paragraph"><p><tt><strong>array</strong> <em>option arrayName ?arg...?</em></tt></p></div>
+<div class="paragraph"><p>This command performs one of several operations on the
+variable given by <tt><em>arrayName</em></tt>.</p></div>
+<div class="paragraph"><p>Note that in general, if the named array does not exist, the <tt><em>array</em></tt> command behaves
+as though the array exists but is empty.</p></div>
+<div class="paragraph"><p>The <tt><em>option</em></tt> argument determines what action is carried out by the
+command.  The legal <tt><em>options</em></tt> (which may be abbreviated) are:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>array exists</strong> <em>arrayName</em></tt>
+</dt>
+<dd>
+<p>
+    Returns 1 if arrayName is an array variable, 0 if there is
+    no variable by that name.  This command is essentially
+    identical to <a href="#_info"><strong><tt>info</tt></strong></a> <tt>exists</tt>
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>array get</strong> <em>arrayName ?pattern?</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a list containing pairs of elements. The first
+    element in each pair is the name of an element in arrayName
+    and the second element of each pair is the value of the
+    array element. The order of the pairs is undefined. If
+    pattern is not specified, then all of the elements of the
+    array are included in the result. If pattern is specified,
+    then only those elements whose names match pattern (using
+    the matching rules of string match) are included. If arrayName
+    isn&#8217;t the name of an array variable, or if the array contains
+    no elements, then an empty list is returned.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>array names</strong> <em>arrayName ?pattern?</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a list containing the names of all of the elements
+    in the array that match pattern. If pattern is omitted then
+    the command returns all of the element names in the array.
+    If pattern is specified, then only those elements whose
+    names match pattern (using the matching rules of string
+    match) are included. If there are no (matching) elements
+    in the array, or if arrayName isn&#8217;t the name of an array
+    variable, then an empty string is returned.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>array set</strong> <em>arrayName list</em></tt>
+</dt>
+<dd>
+<p>
+    Sets the values of one or more elements in arrayName. list
+    must have a form like that returned by array get, consisting
+    of an even number of elements. Each odd-numbered element
+    in list is treated as an element name within arrayName, and
+    the following element in list is used as a new value for
+    that array element. If the variable arrayName does not
+    already exist and list is empty, arrayName is created with
+    an empty array value.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>array size</strong> <em>arrayName</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the number of elements in the array. If arrayName
+    isn&#8217;t the name of an array then 0 is returned.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>array unset</strong> <em>arrayName ?pattern?</em></tt>
+</dt>
+<dd>
+<p>
+    Unsets all of the elements in the array that match pattern
+    (using the matching rules of string match). If arrayName
+    isn&#8217;t the name of an array variable or there are no matching
+    elements in the array, no error will be raised. If pattern
+    is omitted and arrayName is an array variable, then the
+    command unsets the entire array. The command always returns
+    an empty string.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_break">break</h3>
+<div class="paragraph"><p><tt><strong>break</strong></tt></p></div>
+<div class="paragraph"><p>This command may be invoked only inside the body of a loop command
+such as <a href="#_for"><strong><tt>for</tt></strong></a> or <a href="#_foreach"><strong><tt>foreach</tt></strong></a> or <a href="#_while"><strong><tt>while</tt></strong></a>.  It returns a <tt>JIM_BREAK</tt> code
+to signal the innermost containing loop command to return immediately.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_case">case</h3>
+<div class="paragraph"><p><tt><strong>case</strong> <em>string</em> ?in? <em>patList body ?patList body &#8230;?</em></tt></p></div>
+<div class="paragraph"><p><tt><strong>case</strong> <em>string</em> ?in? {<em>patList body ?patList body &#8230;?</em>}</tt></p></div>
+<div class="paragraph"><p><strong>Note</strong> that the <a href="#_switch"><strong><tt>switch</tt></strong></a> command should generally be preferred unless compatibility
+with Tcl 6.x is desired.</p></div>
+<div class="paragraph"><p>Match <tt><em>string</em></tt> against each of the <tt><em>patList</em></tt> arguments
+in order.  If one matches, then evaluate the following <tt><em>body</em></tt> argument
+by passing it recursively to the Tcl interpreter, and return the result
+of that evaluation.  Each <tt><em>patList</em></tt> argument consists of a single
+pattern or list of patterns.  Each pattern may contain any of the wild-cards
+described under <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>.</p></div>
+<div class="paragraph"><p>If a <tt><em>patList</em></tt> argument is <tt>default</tt>, the corresponding body will be
+evaluated if no <tt><em>patList</em></tt> matches <tt><em>string</em></tt>.  If no <tt><em>patList</em></tt> argument
+matches <tt><em>string</em></tt> and no default is given, then the <a href="#_case"><strong><tt>case</tt></strong></a> command returns
+an empty string.</p></div>
+<div class="paragraph"><p>Two syntaxes are provided.</p></div>
+<div class="paragraph"><p>The first uses a separate argument for each of the patterns and commands;
+this form is convenient if substitutions are desired on some of the
+patterns or commands.</p></div>
+<div class="paragraph"><p>The second form places all of the patterns and commands together into
+a single argument; the argument must have proper list structure, with
+the elements of the list being the patterns and commands.</p></div>
+<div class="paragraph"><p>The second form makes it easy to construct multi-line case commands,
+since the braces around the whole list make it unnecessary to include a
+backslash at the end of each line.</p></div>
+<div class="paragraph"><p>Since the <tt><em>patList</em></tt> arguments are in braces in the second form,
+no command or variable substitutions are performed on them;  this makes
+the behaviour of the second form different than the first form in some
+cases.</p></div>
+<div class="paragraph"><p>Below are some examples of <a href="#_case"><strong><tt>case</tt></strong></a> commands:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>case abc in {a b} {format 1} default {format 2} a* {format 3}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return <em>3</em>,</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>case a in {
+    {a b} {format 1}
+    default {format 2}
+    a* {format 3}
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return <em>1</em>, and</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>case xyz {
+    {a b}
+        {format 1}
+    default
+        {format 2}
+    a*
+        {format 3}
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return <em>2</em>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_catch">catch</h3>
+<div class="paragraph"><p><tt><strong>catch</strong> ?-?no?<em>code ...</em>? ?--? <em>command ?resultVarName? ?optionsVarName?</em></tt></p></div>
+<div class="paragraph"><p>The <a href="#_catch"><strong><tt>catch</tt></strong></a> command may be used to prevent errors from aborting
+command interpretation.  <a href="#_catch"><strong><tt>catch</tt></strong></a> evaluates <tt><em>command</em></tt>, and returns a
+<tt>JIM_OK</tt> code, regardless of any errors that might occur while
+executing <tt><em>command</em></tt> (with the possible exception of <tt>JIM_SIGNAL</tt> -
+see below).</p></div>
+<div class="paragraph"><p>The return value from <a href="#_catch"><strong><tt>catch</tt></strong></a> is a decimal string giving the code
+returned by the Tcl interpreter after executing <tt><em>command</em></tt>.  This
+will be <em>0</em> (<tt>JIM_OK</tt>) if there were no errors in <tt><em>command</em></tt>; otherwise
+it will have a non-zero value corresponding to one of the exceptional
+return codes (see jim.h for the definitions of code values, or the
+<a href="#_info"><strong><tt>info</tt></strong></a> <tt>returncodes</tt> command).</p></div>
+<div class="paragraph"><p>If the <tt><em>resultVarName</em></tt> argument is given, then it gives the name
+of a variable; <a href="#_catch"><strong><tt>catch</tt></strong></a> will set the value of the variable to the
+string returned from <tt><em>command</em></tt> (either a result or an error message).</p></div>
+<div class="paragraph"><p>If the <tt><em>optionsVarName</em></tt> argument is given, then it gives the name
+of a variable; <a href="#_catch"><strong><tt>catch</tt></strong></a> will set the value of the variable to a
+dictionary. For any return code other than <tt>JIM_RETURN</tt>, the value
+for the key <tt>-code</tt> will be set to the return code. For <tt>JIM_RETURN</tt>
+it will be set to the code given in <a href="#_return"><strong><tt>return</tt></strong></a> <tt>-code</tt>. Additionally,
+for the return code <tt>JIM_ERR</tt>, the value of the key <tt>-errorinfo</tt>
+will contain the current stack trace (the same result as <a href="#_info"><strong><tt>info</tt></strong></a> <tt>stacktrace</tt>),
+the value of the key <tt>-errorcode</tt> will contain the
+same value as the global variable $::errorCode, and the value of
+the key <tt>-level</tt> will be the current return level (see <a href="#_return"><strong><tt>return</tt></strong></a> <tt>-level</tt>).
+This can be useful to rethrow an error:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>if {[catch {...} msg opts]} {
+    ...maybe do something with the error...
+    incr opts(-level)
+    return {*}$opts $msg
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>Normally <a href="#_catch"><strong><tt>catch</tt></strong></a> will <tt><em>not</em></tt> catch any of the codes <tt>JIM_EXIT</tt>, <tt>JIM_EVAL</tt> or <tt>JIM_SIGNAL</tt>.
+The set of codes which will be caught may be modified by specifying the one more codes before
+<tt><em>command</em></tt>.</p></div>
+<div class="paragraph"><p>e.g. To catch <tt>JIM_EXIT</tt> but not <tt>JIM_BREAK</tt> or <tt>JIM_CONTINUE</tt></p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>catch -exit -nobreak -nocontinue -- { ... }</tt></pre>
+</div></div>
+<div class="paragraph"><p>The use of <tt>--</tt> is optional. It signifies that no more return code options follow.</p></div>
+<div class="paragraph"><p>Note that if a signal marked as <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>handle</tt> is caught with <a href="#_catch"><strong><tt>catch</tt></strong></a> <tt>-signal</tt>, the return value
+(stored in <tt><em>resultVarName</em></tt>) is name of the signal caught.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_cd">cd</h3>
+<div class="paragraph"><p><tt><strong>cd</strong> <em>dirName</em></tt></p></div>
+<div class="paragraph"><p>Change the current working directory to <tt><em>dirName</em></tt>.</p></div>
+<div class="paragraph"><p>Returns an empty string.</p></div>
+<div class="paragraph"><p>This command can potentially be disruptive to an application, so it may
+be removed in some applications.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_clock">clock</h3>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>clock seconds</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the current time as seconds since the epoch.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>clock format</strong> <em>seconds</em> ?<strong>-format</strong> <em>format?</em></tt>
+</dt>
+<dd>
+<p>
+    Format the given time (seconds since the epoch) according to the given
+    format. See strftime(3) for supported formats.
+    If no format is supplied, "%c" is used.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>clock scan</strong> <em>str</em> <strong>-format</strong> <em>format</em></tt>
+</dt>
+<dd>
+<p>
+    Scan the given time string using the given format string.
+    See strptime(3) for supported formats.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_close">close</h3>
+<div class="paragraph"><p><tt><strong>close</strong> <em>fileId</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>close</strong></tt></p></div>
+<div class="paragraph"><p>Closes the file given by <tt><em>fileId</em></tt>.
+<tt><em>fileId</em></tt> must be the return value from a previous invocation
+of the <a href="#_open"><strong><tt>open</tt></strong></a> command; after this command, it should not be
+used anymore.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_collect">collect</h3>
+<div class="paragraph"><p><tt><strong>collect</strong></tt></p></div>
+<div class="paragraph"><p>Normally reference garbage collection is automatically performed periodically.
+However it may be run immediately with the <a href="#_collect"><strong><tt>collect</tt></strong></a> command.</p></div>
+<div class="paragraph"><p>See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_concat">concat</h3>
+<div class="paragraph"><p><tt><strong>concat</strong> <em>arg ?arg ...?</em></tt></p></div>
+<div class="paragraph"><p>This command treats each argument as a list and concatenates them
+into a single list.  It permits any number of arguments.  For example,
+the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>concat a b {c d e} {f {g h}}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>a b c d e f {g h}</tt></pre>
+</div></div>
+<div class="paragraph"><p>as its result.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_continue">continue</h3>
+<div class="paragraph"><p><tt><strong>continue</strong></tt></p></div>
+<div class="paragraph"><p>This command may be invoked only inside the body of a loop command such
+as <a href="#_for"><strong><tt>for</tt></strong></a> or <a href="#_foreach"><strong><tt>foreach</tt></strong></a> or <a href="#_while"><strong><tt>while</tt></strong></a>.  It returns a  <tt>JIM_CONTINUE</tt> code to
+signal the innermost containing loop command to skip the remainder of
+the loop&#8217;s body but continue with the next iteration of the loop.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_curry">curry</h3>
+<div class="paragraph"><p><tt><strong>alias</strong> <em>args...</em></tt></p></div>
+<div class="paragraph"><p>Similar to <a href="#_alias"><strong><tt>alias</tt></strong></a> except it creates an anonymous procedure (lambda) instead of
+a named procedure.</p></div>
+<div class="paragraph"><p>the following creates a local, unnamed alias for the command <a href="#_info"><strong><tt>info</tt></strong></a> <tt>exists</tt>.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set e [local curry info exists]
+if {[$e var]} {
+  ...
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p><a href="#_curry"><strong><tt>curry</tt></strong></a> returns the name of the procedure.</p></div>
+<div class="paragraph"><p>See also <a href="#_proc"><strong><tt>proc</tt></strong></a>, <a href="#_alias"><strong><tt>alias</tt></strong></a>, <a href="#_lambda"><strong><tt>lambda</tt></strong></a>, <a href="#_local"><strong><tt>local</tt></strong></a>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_dict">dict</h3>
+<div class="paragraph"><p><tt><strong>dict</strong> <em>option ?arg...?</em></tt></p></div>
+<div class="paragraph"><p>Performs one of several operations on dictionary values.</p></div>
+<div class="paragraph"><p>The <tt><em>option</em></tt> argument determines what action is carried out by the
+command.  The legal <tt><em>options</em></tt> are:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>dict create</strong> <em>?key value ...?</em></tt>
+</dt>
+<dd>
+<p>
+    Create and return a new dictionary value that contains each of
+    the key/value mappings listed as  arguments (keys and values
+    alternating, with each key being followed by its associated
+    value.)
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict exists</strong> <em>dictionary key ?key ...?</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a boolean value indicating whether the given key (or path
+    of keys through a set of nested dictionaries) exists in the given
+    dictionary value.  This returns a true value exactly when <a href="#_dict"><strong><tt>dict</tt></strong></a> <tt>get</tt>
+    on that path will succeed.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict get</strong> <em>dictionary ?key ...?</em></tt>
+</dt>
+<dd>
+<p>
+    Given a dictionary value (first argument) and a key (second argument),
+    this will retrieve the value for that key. Where several keys are
+    supplied, the behaviour of the command shall be as if the result
+    of "<a href="#_dict"><strong><tt>dict</tt></strong></a> <tt>get $dictVal $key</tt>" was passed as the first argument to
+    dict get with the remaining arguments as second (and possibly
+    subsequent) arguments. This facilitates lookups in nested dictionaries.
+    If no keys are provided, dict would return a list containing pairs
+    of elements in a man- ner similar to array get. That is, the first
+    element of each pair would be the key and the second element would
+    be the value for that key.  It is an error to attempt to retrieve
+    a value for a key that is not present in the dictionary.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict keys</strong> <em>dictionary ?pattern?</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a list of the keys in the dictionary.
+    If pattern is specified, then only those keys whose
+    names match <tt><em>pattern</em></tt> (using the matching rules of string
+    match) are included.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict merge</strong> ?<em>dictionary ...</em>?</tt>
+</dt>
+<dd>
+<p>
+    Return a dictionary that contains the contents of each of the
+    <tt><em>dictionary</em></tt> arguments. Where two (or more) dictionaries
+    contain a mapping for the same key, the resulting dictionary
+    maps that key to the value according to the last dictionary on
+    the command line containing a mapping for that key.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict set</strong> <em>dictionaryName key ?key ...? value</em></tt>
+</dt>
+<dd>
+<p>
+    This operation takes the <tt><em>name</em></tt> of a variable containing a dictionary
+    value and places an updated dictionary value in that variable
+    containing a mapping from the given key to the given value. When
+    multiple keys are present, this operation creates or updates a chain
+    of nested dictionaries.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict size</strong> <em>dictionary</em></tt>
+</dt>
+<dd>
+<p>
+    Return the number of key/value mappings in the given dictionary value.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict unset</strong> <em>dictionaryName key ?key ...? value</em></tt>
+</dt>
+<dd>
+<p>
+    This operation (the companion to <a href="#_dict"><strong><tt>dict</tt></strong></a> <tt>set</tt>) takes the name of a
+    variable containing a dictionary value and places an updated
+    dictionary value in that variable that does not contain a mapping
+    for the given key. Where multiple keys are present, this describes
+    a path through nested dictionaries to the mapping to remove. At
+    least one key must be specified, but the last key on the key-path
+    need not exist. All other components on the path must exist.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>dict with</strong> <em>dictionaryName key ?key ...? script</em></tt>
+</dt>
+<dd>
+<p>
+    Execute the Tcl script in <tt><em>script</em></tt> with the value for each
+    key in <tt><em>dictionaryName</em></tt> mapped to a variable with the same
+    name. Where one or more keys are given, these indicate a chain
+    of nested dictionaries, with the innermost dictionary being the
+    one opened out for the execution of body. Making <tt><em>dictionaryName</em></tt>
+    unreadable will make the updates to the dictionary be discarded,
+    and this also happens if the contents of <tt><em>dictionaryName</em></tt> are
+    adjusted so that the chain of dictionaries no longer exists.
+    The result of <a href="#_dict"><strong><tt>dict</tt></strong></a> <tt>with</tt> is (unless some kind of error occurs)
+    the result of the evaluation of body.
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    The variables are mapped in the scope enclosing the <a href="#_dict"><strong><tt>dict</tt></strong></a> <tt>with</tt>;
+    it is recommended that this command only be used in a local
+    scope (procedure). Because of this, the variables set by
+    <a href="#_dict"><strong><tt>dict</tt></strong></a> <tt>with</tt> will continue to exist after the command finishes (unless
+    explicitly unset). Note that changes to the contents of <tt><em>dictionaryName</em></tt>
+    only happen when <tt><em>script</em></tt> terminates.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p><tt><strong>dict for, values, incr, append, lappend, update, info, replace</strong></tt> to be documented&#8230;</p></div>
+</div>
+<div class="sect2">
+<h3 id="_env">env</h3>
+<div class="paragraph"><p><tt><strong>env</strong> <em>?name? ?default?</em></tt></p></div>
+<div class="paragraph"><p>If <tt><em>name</em></tt> is supplied, returns the value of <tt><em>name</em></tt> from the initial
+environment (see getenv(3)). An error is returned if <tt><em>name</em></tt> does not
+exist in the environment, unless <tt><em>default</em></tt> is supplied - in which case
+that value is returned instead.</p></div>
+<div class="paragraph"><p>If no arguments are supplied, returns a list of all environment variables
+and their values as <tt>{name value ...}</tt></p></div>
+<div class="paragraph"><p>See also the global variable <tt>::env</tt></p></div>
+</div>
+<div class="sect2">
+<h3 id="_eof">eof</h3>
+<div class="paragraph"><p><tt><strong>eof</strong> <em>fileId</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>eof</strong></tt></p></div>
+<div class="paragraph"><p>Returns 1 if an end-of-file condition has occurred on <tt><em>fileId</em></tt>,
+0 otherwise.</p></div>
+<div class="paragraph"><p><tt><em>fileId</em></tt> must have been the return value from a previous call to <a href="#_open"><strong><tt>open</tt></strong></a>,
+or it may be <tt>stdin</tt>, <tt>stdout</tt>, or <tt>stderr</tt> to refer to one of the
+standard I/O channels.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_error">error</h3>
+<div class="paragraph"><p><tt><strong>error</strong> <em>message ?stacktrace?</em></tt></p></div>
+<div class="paragraph"><p>Returns a <tt>JIM_ERR</tt> code, which causes command interpretation to be
+unwound.  <tt><em>message</em></tt> is a string that is returned to the application
+to indicate what went wrong.</p></div>
+<div class="paragraph"><p>If the <tt><em>stacktrace</em></tt> argument is provided and is non-empty,
+it is used to initialize the stacktrace.</p></div>
+<div class="paragraph"><p>This feature is most useful in conjunction with the <a href="#_catch"><strong><tt>catch</tt></strong></a> command:
+if a caught error cannot be handled successfully, <tt><em>stacktrace</em></tt> can be used
+to return a stack trace reflecting the original point of occurrence
+of the error:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>catch {...} errMsg
+...
+error $errMsg [info stacktrace]</tt></pre>
+</div></div>
+<div class="paragraph"><p>See also <tt>errorInfo</tt>, <a href="#_info"><strong><tt>info</tt></strong></a> <tt>stacktrace</tt>, <a href="#_catch"><strong><tt>catch</tt></strong></a> and <a href="#_return"><strong><tt>return</tt></strong></a></p></div>
+</div>
+<div class="sect2">
+<h3 id="_errorinfo">errorInfo</h3>
+<div class="paragraph"><p><tt><strong>errorInfo</strong> <em>error ?stacktrace?</em></tt></p></div>
+<div class="paragraph"><p>Returns a human-readable representation of the given error message and stack trace.
+Typical usage is:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>if {[catch {...} error]} {
+    puts stderr [errorInfo $error [info stacktrace]]
+    exit 1
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>See also <a href="#_error"><strong><tt>error</tt></strong></a>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_eval">eval</h3>
+<div class="paragraph"><p><tt><strong>eval</strong> <em>arg ?arg...?</em></tt></p></div>
+<div class="paragraph"><p><a href="#_eval"><strong><tt>eval</tt></strong></a> takes one or more arguments, which together comprise a Tcl
+command (or collection of Tcl commands separated by newlines in the
+usual way).  <a href="#_eval"><strong><tt>eval</tt></strong></a> concatenates all its arguments in the same
+fashion as the <a href="#_concat"><strong><tt>concat</tt></strong></a> command, passes the concatenated string to the
+Tcl interpreter recursively, and returns the result of that
+evaluation (or any error generated by it).</p></div>
+</div>
+<div class="sect2">
+<h3 id="_exec">exec</h3>
+<div class="paragraph"><p><tt><strong>exec</strong> <em>arg ?arg...?</em></tt></p></div>
+<div class="paragraph"><p>This command treats its arguments as the specification
+of one or more UNIX commands to execute as subprocesses.
+The commands take the form of a standard shell pipeline;
+<tt>|</tt> arguments separate commands in the
+pipeline and cause standard output of the preceding command
+to be piped into standard input of the next command (or <tt>|&amp;</tt> for
+both standard output and standard error).</p></div>
+<div class="paragraph"><p>Under normal conditions the result of the <a href="#_exec"><strong><tt>exec</tt></strong></a> command
+consists of the standard output produced by the last command
+in the pipeline.</p></div>
+<div class="paragraph"><p>If any of the commands in the pipeline exit abnormally or
+are killed or suspended, then <a href="#_exec"><strong><tt>exec</tt></strong></a> will return an error
+and the error message will include the pipeline&#8217;s output followed by
+error messages describing the abnormal terminations.</p></div>
+<div class="paragraph"><p>If any of the commands writes to its standard error file,
+then <a href="#_exec"><strong><tt>exec</tt></strong></a> will return an error, and the error message
+will include the pipeline&#8217;s output, followed by messages
+about abnormal terminations (if any), followed by the standard error
+output.</p></div>
+<div class="paragraph"><p>If the last character of the result or error message
+is a newline then that character is deleted from the result
+or error message for consistency with normal
+Tcl return values.</p></div>
+<div class="paragraph"><p>An <tt><em>arg</em></tt> may have one of the following special forms:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>&gt;filename</tt>
+</dt>
+<dd>
+<p>
+    The standard output of the last command in the pipeline
+    is redirected to the file.  In this situation <a href="#_exec"><strong><tt>exec</tt></strong></a>
+    will normally return an empty string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&gt;&gt;filename</tt>
+</dt>
+<dd>
+<p>
+    As above, but append to the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&gt;@fileId</tt>
+</dt>
+<dd>
+<p>
+    The standard output of the last command in the pipeline is
+    redirected to the given (writable) file descriptor (e.g. stdout,
+    stderr, or the result of <a href="#_open"><strong><tt>open</tt></strong></a>). In this situation <a href="#_exec"><strong><tt>exec</tt></strong></a>
+    will normally return an empty string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>2&gt;filename</tt>
+</dt>
+<dd>
+<p>
+    The standard error of the last command in the pipeline
+    is redirected to the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>2&gt;&gt;filename</tt>
+</dt>
+<dd>
+<p>
+    As above, but append to the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>2&gt;@fileId</tt>
+</dt>
+<dd>
+<p>
+    The standard error of the last command in the pipeline is
+    redirected to the given (writable) file descriptor.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>2&gt;@1</tt>
+</dt>
+<dd>
+<p>
+    The standard error of the last command in the pipeline is
+    redirected to the same file descriptor as the standard output.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&gt;&amp;filename</tt>
+</dt>
+<dd>
+<p>
+    Both the standard output and standard error of the last command
+    in the pipeline is redirected to the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&gt;&gt;&amp;filename</tt>
+</dt>
+<dd>
+<p>
+    As above, but append to the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&lt;filename</tt>
+</dt>
+<dd>
+<p>
+    The standard input of the first command in the pipeline
+    is taken from the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&lt;&lt;string</tt>
+</dt>
+<dd>
+<p>
+    The standard input of the first command is taken as the
+    given immediate value.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>&lt;@fileId</tt>
+</dt>
+<dd>
+<p>
+    The standard input of the first command in the pipeline
+    is taken from the given (readable) file descriptor.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>If there is no redirection of standard input, standard error
+or standard output, these are connected to the corresponding
+input or output of the application.</p></div>
+<div class="paragraph"><p>If the last <tt><em>arg</em></tt> is <tt>&amp;</tt> then the command will be
+executed in background.
+In this case the standard output from the last command
+in the pipeline will
+go to the application&#8217;s standard output unless
+redirected in the command, and error output from all
+the commands in the pipeline will go to the application&#8217;s
+standard error file. The return value of exec in this case
+is a list of process ids (pids) in the pipeline.</p></div>
+<div class="paragraph"><p>Each <tt><em>arg</em></tt> becomes one word for a command, except for
+<tt>|</tt>, <tt>&lt;</tt>, <tt>&lt;&lt;</tt>, <tt>&gt;</tt>, and <tt>&amp;</tt> arguments, and the
+arguments that follow <tt>&lt;</tt>, <tt>&lt;&lt;</tt>, and <tt>&gt;</tt>.</p></div>
+<div class="paragraph"><p>The first word in each command is taken as the command name;
+the directories in the PATH environment variable are searched for
+an executable by the given name.</p></div>
+<div class="paragraph"><p>No <a href="#_glob"><strong><tt>glob</tt></strong></a> expansion or other shell-like substitutions
+are performed on the arguments to commands.</p></div>
+<div class="paragraph"><p>If the command fails, the global $::errorCode (and the -errorcode
+option in <a href="#_catch"><strong><tt>catch</tt></strong></a>) will be set to a list, as follows:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>CHILDKILLED</strong> <em>pid sigName msg</em></tt>
+</dt>
+<dd>
+<p>
+        This format is used when a child process has been killed
+        because of a signal. The pid element will be the process&#8217;s
+        identifier (in decimal). The sigName element will be the
+        symbolic name of the signal that caused the process to
+        terminate; it will be one of the names from the include
+        file signal.h, such as SIGPIPE. The msg element will be a
+        short human-readable message describing the signal, such
+        as "write on pipe with no readers" for SIGPIPE.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>CHILDSUSP</strong> <em>pid sigName msg</em></tt>
+</dt>
+<dd>
+<p>
+        This format is used when a child process has been suspended
+        because of a signal. The pid element will be the process&#8217;s
+        identifier, in decimal. The sigName element will be the
+        symbolic name of the signal that caused the process to
+        suspend; this will be one of the names from the include
+        file signal.h, such as SIGTTIN. The msg element will be a
+        short human-readable message describing the signal, such
+        as "background tty read" for SIGTTIN.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>CHILDSTATUS</strong> <em>pid code</em></tt>
+</dt>
+<dd>
+<p>
+        This format is used when a child process has exited with a
+        non-zero exit status. The pid element will be the process&#8217;s
+        identifier (in decimal) and the code element will be the
+        exit code returned by the process (also in decimal).
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>The environment for the executed command is set from $::env (unless
+this variable is unset, in which case the original environment is used).</p></div>
+</div>
+<div class="sect2">
+<h3 id="_exists">exists</h3>
+<div class="paragraph"><p><tt><strong>exists ?-var|-proc|-command|-alias?</strong> <em>name</em></tt></p></div>
+<div class="paragraph"><p>Checks the existence of the given variable, procedure, command
+or alias respectively and returns 1 if it exists or 0 if not.  This command
+provides a more simplified/convenient version of <a href="#_info"><strong><tt>info</tt></strong></a> <tt>exists</tt>,
+<a href="#_info"><strong><tt>info</tt></strong></a> <tt>procs</tt> and <a href="#_info"><strong><tt>info</tt></strong></a> <tt>commands</tt>.</p></div>
+<div class="paragraph"><p>If the type is omitted, a type of <em>-var</em> is used. The type may be abbreviated.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_exit">exit</h3>
+<div class="paragraph"><p><tt><strong>exit</strong> <em>?returnCode?</em></tt></p></div>
+<div class="paragraph"><p>Terminate the process, returning <tt><em>returnCode</em></tt> to the
+parent as the exit status.</p></div>
+<div class="paragraph"><p>If <tt><em>returnCode</em></tt> isn&#8217;t specified then it defaults
+to 0.</p></div>
+<div class="paragraph"><p>Note that exit can be caught with <a href="#_catch"><strong><tt>catch</tt></strong></a>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_expr">expr</h3>
+<div class="paragraph"><p><tt><strong>expr</strong> <em>arg</em></tt></p></div>
+<div class="paragraph"><p>Calls the expression processor to evaluate <tt><em>arg</em></tt>, and returns
+the result as a string.  See the section EXPRESSIONS above.</p></div>
+<div class="paragraph"><p>Note that Jim supports a shorthand syntax for <a href="#_expr"><strong><tt>expr</tt></strong></a> as <tt>$(...)</tt>
+The following two are identical.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set x [expr {3 * 2 + 1}]
+set x $(3 * 2 + 1)</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_file">file</h3>
+<div class="paragraph"><p><tt><strong>file</strong> <em>option name ?arg...?</em></tt></p></div>
+<div class="paragraph"><p>Operate on a file or a file name.  <tt><em>name</em></tt> is the name of a file.</p></div>
+<div class="paragraph"><p><tt><em>option</em></tt> indicates what to do with the file name.  Any unique
+abbreviation for <tt><em>option</em></tt> is acceptable.  The valid options are:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>file atime</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return a decimal string giving the time at which file <tt><em>name</em></tt>
+    was last accessed.  The time is measured in the standard UNIX
+    fashion as seconds from a fixed starting time (often January 1, 1970).
+    If the file doesn&#8217;t exist or its access time cannot be queried then an
+    error is generated.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file copy ?-force?</strong> <em>source target</em></tt>
+</dt>
+<dd>
+<p>
+    Copies file <tt><em>source</em></tt> to file <tt><em>target</em></tt>. The source file must exist.
+    The target file must not exist, unless <tt>-force</tt> is specified.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file delete ?-force?</strong> <em>name...</em></tt>
+</dt>
+<dd>
+<p>
+    Deletes file or directory <tt><em>name</em></tt>. If the file or directory doesn&#8217;t exist, nothing happens.
+    If it can&#8217;t be deleted, an error is generated. Non-empty directories will not be deleted
+    unless the <tt>-force</tt> options is given. In this case no errors will be generated, even
+    if the file/directory can&#8217;t be deleted.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file dirname</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return all of the characters in <tt><em>name</em></tt> up to but not including
+    the last slash character.  If there are no slashes in <tt><em>name</em></tt>
+    then return <tt>.</tt> (a single dot).  If the last slash in <tt><em>name</em></tt> is its first
+    character, then return <tt>/</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file executable</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return <em>1</em> if file <tt><em>name</em></tt> is executable by
+    the current user, <em>0</em> otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file exists</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return <em>1</em> if file <tt><em>name</em></tt> exists and the current user has
+    search privileges for the directories leading to it, <em>0</em> otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file extension</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return all of the characters in <tt><em>name</em></tt> after and including the
+    last dot in <tt><em>name</em></tt>.  If there is no dot in <tt><em>name</em></tt> then return
+    the empty string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file isdirectory</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return <em>1</em> if file <tt><em>name</em></tt> is a directory,
+    <em>0</em> otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file isfile</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return <em>1</em> if file <tt><em>name</em></tt> is a regular file,
+    <em>0</em> otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file join</strong> <em>arg...</em></tt>
+</dt>
+<dd>
+<p>
+    Joins multiple path components. Note that if any components is
+    an absolute path, the preceding components are ignored.
+    Thus <tt>"<a href="#_file"><strong><tt>file</tt></strong></a> join /tmp /root"</tt> returns <tt>"/root"</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file lstat</strong> <em>name varName</em></tt>
+</dt>
+<dd>
+<p>
+    Same as <em>stat</em> option (see below) except uses the <tt><em>lstat</em></tt>
+    kernel call instead of <tt><em>stat</em></tt>.  This means that if <tt><em>name</em></tt>
+    refers to a symbolic link the information returned in <tt><em>varName</em></tt>
+    is for the link rather than the file it refers to.  On systems that
+    don&#8217;t support symbolic links this option behaves exactly the same
+    as the <em>stat</em> option.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file mkdir</strong> <em>dir1 ?dir2...?</em></tt>
+</dt>
+<dd>
+<p>
+    Creates each directory specified. For each pathname <tt><em>dir</em></tt> specified,
+    this command will create all non-existing parent directories
+    as well as <tt><em>dir</em></tt> itself. If an existing directory is specified,
+    then no action is taken and no error is returned. Trying to
+    overwrite an existing file with a directory will result in an
+    error.  Arguments are processed in the order specified, halting
+    at the first error, if any.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file mtime</strong> <em>name ?time?</em></tt>
+</dt>
+<dd>
+<p>
+    Return a decimal string giving the time at which file <tt><em>name</em></tt>
+    was last modified.  The time is measured in the standard UNIX
+    fashion as seconds from a fixed starting time (often January 1, 1970).
+    If the file doesn&#8217;t exist or its modified time cannot be queried then an
+    error is generated. If <tt><em>time</em></tt> is given, sets the modification time
+    of the file to the given value.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file normalize</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return the normalized path of <tt><em>name</em></tt>. See <em>realpath(3)</em>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file owned</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return <em>1</em> if file <tt><em>name</em></tt> is owned by the current user,
+    <em>0</em> otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file readable</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return <em>1</em> if file <tt><em>name</em></tt> is readable by
+    the current user, <em>0</em> otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file readlink</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the value of the symbolic link given by <tt><em>name</em></tt> (i.e. the
+    name of the file it points to).  If
+    <tt><em>name</em></tt> isn&#8217;t a symbolic link or its value cannot be read, then
+    an error is returned.  On systems that don&#8217;t support symbolic links
+    this option is undefined.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file rename</strong> <em>oldname</em> <em>newname</em></tt>
+</dt>
+<dd>
+<p>
+    Renames the file from the old name to the new name.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file rootname</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return all of the characters in <tt><em>name</em></tt> up to but not including
+    the last <em>.</em> character in the name.  If <tt><em>name</em></tt> doesn&#8217;t contain
+    a dot, then return <tt><em>name</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file size</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return a decimal string giving the size of file <tt><em>name</em></tt> in bytes.
+    If the file doesn&#8217;t exist or its size cannot be queried then an
+    error is generated.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file stat</strong> <em>name ?varName?</em></tt>
+</dt>
+<dd>
+<p>
+    Invoke the <em>stat</em> kernel call on <tt><em>name</em></tt>, and return the result
+        as a dictionary with the following keys: <em>atime</em>,
+    <em>ctime</em>, <em>dev</em>, <em>gid</em>, <em>ino</em>, <em>mode</em>, <em>mtime</em>,
+    <em>nlink</em>, <em>size</em>, <em>type</em>, <em>uid</em>.
+    Each element except <em>type</em> is a decimal string with the value of
+    the corresponding field from the <em>stat</em> return structure; see the
+    manual entry for <em>stat</em> for details on the meanings of the values.
+    The <em>type</em> element gives the type of the file in the same form
+    returned by the command <a href="#_file"><strong><tt>file</tt></strong></a> <tt>type</tt>.
+        If <tt><em>varName</em></tt> is specified, it is taken to be the name of an array
+        variable and the values are also stored into the array.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file tail</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return all of the characters in <tt><em>name</em></tt> after the last slash.
+    If <tt><em>name</em></tt> contains no slashes then return <tt><em>name</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file tempfile</strong> <em>?template?</em></tt>
+</dt>
+<dd>
+<p>
+    Creates and returns the name of a unique temporary file. If <tt><em>template</em></tt> is omitted, a
+    default template will be used to place the file in /tmp. See <em>mkstemp(3)</em> for
+    the format of the template and security concerns.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file type</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a string giving the type of file <tt><em>name</em></tt>, which will be
+    one of <tt>file</tt>, <tt>directory</tt>, <tt>characterSpecial</tt>,
+    <tt>blockSpecial</tt>, <tt>fifo</tt>, <tt>link</tt>, or <tt>socket</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>file writable</strong> <em>name</em></tt>
+</dt>
+<dd>
+<p>
+    Return <em>1</em> if file <tt><em>name</em></tt> is writable by
+    the current user, <em>0</em> otherwise.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>The <a href="#_file"><strong><tt>file</tt></strong></a> commands that return 0/1 results are often used in
+conditional or looping commands, for example:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>if {![file exists foo]} {
+    error {bad file name}
+} else {
+    ...
+}</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_finalize">finalize</h3>
+<div class="paragraph"><p><tt><strong>finalize</strong> <em>reference ?command?</em></tt></p></div>
+<div class="paragraph"><p>If <tt><em>command</em></tt> is omitted, returns the finalizer command for the given reference.</p></div>
+<div class="paragraph"><p>Otherwise, sets a new finalizer command for the given reference. <tt><em>command</em></tt> may be
+the empty string to remove the current finalizer.</p></div>
+<div class="paragraph"><p>The reference must be a valid reference create with the <a href="#_ref"><strong><tt>ref</tt></strong></a>
+command.</p></div>
+<div class="paragraph"><p>See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_flush">flush</h3>
+<div class="paragraph"><p><tt><strong>flush</strong> <em>fileId</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>flush</strong></tt></p></div>
+<div class="paragraph"><p>Flushes any output that has been buffered for <tt><em>fileId</em></tt>.  <tt><em>fileId</em></tt> must
+have been the return value from a previous call to <a href="#_open"><strong><tt>open</tt></strong></a>, or it may be
+<tt>stdout</tt> or <tt>stderr</tt> to access one of the standard I/O streams; it must
+refer to a file that was opened for writing.  This command returns an
+empty string.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_for">for</h3>
+<div class="paragraph"><p><tt><strong>for</strong> <em>start test next body</em></tt></p></div>
+<div class="paragraph"><p><a href="#_for"><strong><tt>for</tt></strong></a> is a looping command, similar in structure to the C <a href="#_for"><strong><tt>for</tt></strong></a> statement.
+The <tt><em>start</em></tt>, <tt><em>next</em></tt>, and <tt><em>body</em></tt> arguments must be Tcl command strings,
+and <tt><em>test</em></tt> is an expression string.</p></div>
+<div class="paragraph"><p>The <a href="#_for"><strong><tt>for</tt></strong></a> command first invokes the Tcl interpreter to execute <tt><em>start</em></tt>.
+Then it repeatedly evaluates <tt><em>test</em></tt> as an expression; if the result is
+non-zero it invokes the Tcl interpreter on <tt><em>body</em></tt>, then invokes the Tcl
+interpreter on <tt><em>next</em></tt>, then repeats the loop.  The command terminates
+when <tt><em>test</em></tt> evaluates to 0.</p></div>
+<div class="paragraph"><p>If a <a href="#_continue"><strong><tt>continue</tt></strong></a> command is invoked within <tt><em>body</em></tt> then any remaining
+commands in the current execution of <tt><em>body</em></tt> are skipped; processing
+continues by invoking the Tcl interpreter on <tt><em>next</em></tt>, then evaluating
+<tt><em>test</em></tt>, and so on.</p></div>
+<div class="paragraph"><p>If a <a href="#_break"><strong><tt>break</tt></strong></a> command is invoked within <tt><em>body</em></tt> or <tt><em>next</em></tt>, then the <a href="#_for"><strong><tt>for</tt></strong></a>
+command will return immediately.</p></div>
+<div class="paragraph"><p>The operation of <a href="#_break"><strong><tt>break</tt></strong></a> and <a href="#_continue"><strong><tt>continue</tt></strong></a> are similar to the corresponding
+statements in C.</p></div>
+<div class="paragraph"><p><a href="#_for"><strong><tt>for</tt></strong></a> returns an empty string.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_foreach">foreach</h3>
+<div class="paragraph"><p><tt><strong>foreach</strong> <em>varName list body</em></tt></p></div>
+<div class="paragraph"><p><tt><strong>foreach</strong> <em>varList list ?varList2 list2 ...? body</em></tt></p></div>
+<div class="paragraph"><p>In this command, <tt><em>varName</em></tt> is the name of a variable, <tt><em>list</em></tt>
+is a list of values to assign to <tt><em>varName</em></tt>, and <tt><em>body</em></tt> is a
+collection of Tcl commands.</p></div>
+<div class="paragraph"><p>For each field in <tt><em>list</em></tt> (in order from left to right), <a href="#_foreach"><strong><tt>foreach</tt></strong></a> assigns
+the contents of the field to <tt><em>varName</em></tt> (as if the <a href="#_lindex"><strong><tt>lindex</tt></strong></a> command
+had been used to extract the field), then calls the Tcl interpreter to
+execute <tt><em>body</em></tt>.</p></div>
+<div class="paragraph"><p>If instead of being a simple name, <tt><em>varList</em></tt> is used, multiple assignments
+are made each time through the loop, one for each element of <tt><em>varList</em></tt>.</p></div>
+<div class="paragraph"><p>For example, if there are two elements in <tt><em>varList</em></tt> and six elements in
+the list, the loop will be executed three times.</p></div>
+<div class="paragraph"><p>If the length of the list doesn&#8217;t evenly divide by the number of elements
+in <tt><em>varList</em></tt>, the value of the remaining variables in the last iteration
+of the loop are undefined.</p></div>
+<div class="paragraph"><p>The <a href="#_break"><strong><tt>break</tt></strong></a> and <a href="#_continue"><strong><tt>continue</tt></strong></a> statements may be invoked inside <tt><em>body</em></tt>,
+with the same effect as in the <a href="#_for"><strong><tt>for</tt></strong></a> command.</p></div>
+<div class="paragraph"><p><a href="#_foreach"><strong><tt>foreach</tt></strong></a> returns an empty string.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_format">format</h3>
+<div class="paragraph"><p><tt><strong>format</strong> <em>formatString ?arg ...?</em></tt></p></div>
+<div class="paragraph"><p>This command generates a formatted string in the same way as the
+C <em>sprintf</em> procedure (it uses <em>sprintf</em> in its
+implementation).  <tt><em>formatString</em></tt> indicates how to format
+the result, using <tt>%</tt> fields as in <em>sprintf</em>, and the additional
+arguments, if any, provide values to be substituted into the result.</p></div>
+<div class="paragraph"><p>All of the <em>sprintf</em> options are valid; see the <em>sprintf</em>
+man page for details.  Each <tt><em>arg</em></tt> must match the expected type
+from the <tt>%</tt> field in <tt><em>formatString</em></tt>; the <a href="#_format"><strong><tt>format</tt></strong></a> command
+converts each argument to the correct type (floating, integer, etc.)
+before passing it to <em>sprintf</em> for formatting.</p></div>
+<div class="paragraph"><p>The only unusual conversion is for <tt>%c</tt>; in this case the argument
+must be a decimal string, which will then be converted to the corresponding
+ASCII (or UTF-8) character value.</p></div>
+<div class="paragraph"><p>In addition, Jim Tcl provides basic support for conversion to binary with <tt>%b</tt>.</p></div>
+<div class="paragraph"><p><a href="#_format"><strong><tt>format</tt></strong></a> does backslash substitution on its <tt><em>formatString</em></tt>
+argument, so backslash sequences in <tt><em>formatString</em></tt> will be handled
+correctly even if the argument is in braces.</p></div>
+<div class="paragraph"><p>The return value from <a href="#_format"><strong><tt>format</tt></strong></a> is the formatted string.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_getref">getref</h3>
+<div class="paragraph"><p><tt><strong>getref</strong> <em>reference</em></tt></p></div>
+<div class="paragraph"><p>Returns the string associated with <tt><em>reference</em></tt>. The reference must
+be a valid reference create with the <a href="#_ref"><strong><tt>ref</tt></strong></a> command.</p></div>
+<div class="paragraph"><p>See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_gets">gets</h3>
+<div class="paragraph"><p><tt><strong>gets</strong> <em>fileId ?varName?</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>gets</strong> <em>?varName?</em></tt></p></div>
+<div class="paragraph"><p>Reads the next line from the file given by <tt><em>fileId</em></tt> and discards
+the terminating newline character.</p></div>
+<div class="paragraph"><p>If <tt><em>varName</em></tt> is specified, then the line is placed in the variable
+by that name and the return value is a count of the number of characters
+read (not including the newline).</p></div>
+<div class="paragraph"><p>If the end of the file is reached before reading
+any characters then -1 is returned and <tt><em>varName</em></tt> is set to an
+empty string.</p></div>
+<div class="paragraph"><p>If <tt><em>varName</em></tt> is not specified then the return value will be
+the line (minus the newline character) or an empty string if
+the end of the file is reached before reading any characters.</p></div>
+<div class="paragraph"><p>An empty string will also be returned if a line contains no characters
+except the newline, so <a href="#_eof"><strong><tt>eof</tt></strong></a> may have to be used to determine
+what really happened.</p></div>
+<div class="paragraph"><p>If the last character in the file is not a newline character, then
+<a href="#_gets"><strong><tt>gets</tt></strong></a> behaves as if there were an additional newline character
+at the end of the file.</p></div>
+<div class="paragraph"><p><tt><em>fileId</em></tt> must be <tt>stdin</tt> or the return value from a previous
+call to <a href="#_open"><strong><tt>open</tt></strong></a>; it must refer to a file that was opened
+for reading.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_glob">glob</h3>
+<div class="paragraph"><p><tt><strong>glob</strong> ?<strong>-nocomplain</strong>? ?<strong>-directory</strong> <em>dir</em>? ?<strong>--</strong>? <em>pattern ?pattern ...?</em></tt></p></div>
+<div class="paragraph"><p>This command performs filename globbing, using csh rules.  The returned
+value from <a href="#_glob"><strong><tt>glob</tt></strong></a> is the list of expanded filenames.</p></div>
+<div class="paragraph"><p>If <tt>-nocomplain</tt> is specified as the first argument then an empty
+list may be returned;  otherwise an error is returned if the expanded
+list is empty.  The <tt>-nocomplain</tt> argument must be provided
+exactly: an abbreviation will not be accepted.</p></div>
+<div class="paragraph"><p>If <tt>-directory</tt> is given, the <tt><em>dir</em></tt> is understood to contain a
+directory name to search in. This allows globbing inside directories
+whose names may contain glob-sensitive characters. The returned names
+are specified relative to this directory.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_global">global</h3>
+<div class="paragraph"><p><tt><strong>global</strong> <em>varName ?varName ...?</em></tt></p></div>
+<div class="paragraph"><p>This command is ignored unless a Tcl procedure is being interpreted.
+If so, then it declares each given <tt><em>varName</em></tt> to be a global variable
+rather than a local one.  For the duration of the current procedure
+(and only while executing in the current procedure), any reference to
+<tt><em>varName</em></tt> will be bound to a global variable instead
+of a local one.</p></div>
+<div class="paragraph"><p>An alternative to using <a href="#_global"><strong><tt>global</tt></strong></a> is to use the <tt>::</tt> prefix
+to explicitly name a variable in the global scope.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_if">if</h3>
+<div class="paragraph"><p><tt><strong>if</strong> <em>expr1</em> ?<strong>then</strong>? <em>body1</em> <strong>elseif</strong> <em>expr2</em> ?<strong>then</strong>? <em>body2</em> <strong>elseif</strong> ... ?<strong>else</strong>? ?<em>bodyN</em>?</tt></p></div>
+<div class="paragraph"><p>The <a href="#_if"><strong><tt>if</tt></strong></a> command evaluates <tt><em>expr1</em></tt> as an expression (in the same way
+that <a href="#_expr"><strong><tt>expr</tt></strong></a> evaluates its argument).  The value of the expression must
+be numeric; if it is non-zero then <tt><em>body1</em></tt> is executed by passing it to
+the Tcl interpreter.</p></div>
+<div class="paragraph"><p>Otherwise <tt><em>expr2</em></tt> is evaluated as an expression and if it is non-zero
+then <tt><em>body2</em></tt> is executed, and so on.</p></div>
+<div class="paragraph"><p>If none of the expressions evaluates to non-zero then <tt><em>bodyN</em></tt> is executed.</p></div>
+<div class="paragraph"><p>The <tt>then</tt> and <tt>else</tt> arguments are optional "noise words" to make the
+command easier to read.</p></div>
+<div class="paragraph"><p>There may be any number of <tt>elseif</tt> clauses, including zero.  <tt><em>bodyN</em></tt>
+may also be omitted as long as <tt>else</tt> is omitted too.</p></div>
+<div class="paragraph"><p>The return value from the command is the result of the body script that
+was executed, or an empty string if none of the expressions was non-zero
+and there was no <tt><em>bodyN</em></tt>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_incr">incr</h3>
+<div class="paragraph"><p><tt><strong>incr</strong> <em>varName ?increment?</em></tt></p></div>
+<div class="paragraph"><p>Increment the value stored in the variable whose name is <tt><em>varName</em></tt>.
+The value of the variable must be integral.</p></div>
+<div class="paragraph"><p>If <tt><em>increment</em></tt> is supplied then its value (which must be an
+integer) is added to the value of variable <tt><em>varName</em></tt>;  otherwise
+1 is added to <tt><em>varName</em></tt>.</p></div>
+<div class="paragraph"><p>The new value is stored as a decimal string in variable <tt><em>varName</em></tt>
+and also returned as result.</p></div>
+<div class="paragraph"><p>If the variable does not exist, the variable is implicitly created
+and set to <tt>0</tt> first.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_info">info</h3>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>info</strong> <em>option ?arg...?</em></tt>
+</dt>
+<dd>
+<p>
+Provide information about various internals to the Tcl interpreter.
+The legal <tt><em>option</em></tt>'s (which may be abbreviated) are:
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info args</strong> <em>procname</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a list containing the names of the arguments to procedure
+    <tt><em>procname</em></tt>, in order.  <tt><em>procname</em></tt> must be the name of a
+    Tcl command procedure.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info alias</strong> <em>command</em></tt>
+</dt>
+<dd>
+<p>
+    <tt><em>command</em></tt> must be an alias created with <a href="#_alias"><strong><tt>alias</tt></strong></a>. In which case the target
+    command and arguments, as passed to <a href="#_alias"><strong><tt>alias</tt></strong></a> are returned. See <a href="#_exists"><strong><tt>exists</tt></strong></a> <tt>-alias</tt>
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info body</strong> <em>procname</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the body of procedure <tt><em>procname</em></tt>.  <tt><em>procname</em></tt> must be
+    the name of a Tcl command procedure.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info channels</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns a list of all open file handles from <a href="#_open"><strong><tt>open</tt></strong></a> or <a href="#_socket"><strong><tt>socket</tt></strong></a>
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info commands</strong> ?<em>pattern</em>?</tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>pattern</em></tt> isn&#8217;t specified, returns a list of names of all the
+    Tcl commands, including both the built-in commands written in C and
+    the command procedures defined using the <a href="#_proc"><strong><tt>proc</tt></strong></a> command.
+    If <tt><em>pattern</em></tt> is specified, only those names matching <tt><em>pattern</em></tt>
+    are returned.  Matching is determined using the same rules as for
+    <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info complete</strong> <em>command</em> ?<em>missing</em>?</tt>
+</dt>
+<dd>
+<p>
+    Returns 1 if <tt><em>command</em></tt> is a complete Tcl command in the sense of
+    having no unclosed quotes, braces, brackets or array element names,
+    If the command doesn&#8217;t appear to be complete then 0 is returned.
+    This command is typically used in line-oriented input environments
+    to allow users to type in commands that span multiple lines;  if the
+    command isn&#8217;t complete, the script can delay evaluating it until additional
+    lines have been typed to complete the command. If <tt><em>varName</em></tt> is specified, the
+    missing character is stored in the variable with that name.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info exists</strong> <em>varName</em></tt>
+</dt>
+<dd>
+<p>
+    Returns <em>1</em> if the variable named <tt><em>varName</em></tt> exists in the
+    current context (either as a global or local variable), returns <em>0</em>
+    otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info frame</strong> ?<em>number</em>?</tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>number</em></tt> is not specified, this command returns a number
+    which is the same result as <a href="#_info"><strong><tt>info</tt></strong></a> <tt>level</tt> - the current stack frame level.
+    If <tt><em>number</em></tt> is specified, then the result is a list consisting of the procedure,
+    filename and line number for the procedure call at level <tt><em>number</em></tt> on the stack.
+    If <tt><em>number</em></tt> is positive then it selects a particular stack level (1 refers
+    to the top-most active procedure, 2 to the procedure it called, and
+    so on); otherwise it gives a level relative to the current level
+    (0 refers to the current procedure, -1 to its caller, and so on).
+    The level has an identical meaning to <a href="#_info"><strong><tt>info</tt></strong></a> <tt>level</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info globals</strong> ?<em>pattern</em>?</tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>pattern</em></tt> isn&#8217;t specified, returns a list of all the names
+    of currently-defined global variables.
+    If <tt><em>pattern</em></tt> is specified, only those names matching <tt><em>pattern</em></tt>
+    are returned.  Matching is determined using the same rules as for
+    <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info hostname</strong></tt>
+</dt>
+<dd>
+<p>
+    An alias for <a href="#cmd_1"><strong><tt>os.gethostname</tt></strong></a> for compatibility with Tcl 6.x
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info level</strong> ?<em>number</em>?</tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>number</em></tt> is not specified, this command returns a number
+    giving the stack level of the invoking procedure, or 0 if the
+    command is invoked at top-level.  If <tt><em>number</em></tt> is specified,
+    then the result is a list consisting of the name and arguments for the
+    procedure call at level <tt><em>number</em></tt> on the stack.  If <tt><em>number</em></tt>
+    is positive then it selects a particular stack level (1 refers
+    to the top-most active procedure, 2 to the procedure it called, and
+    so on); otherwise it gives a level relative to the current level
+    (0 refers to the current procedure, -1 to its caller, and so on).
+    See the <a href="#_uplevel"><strong><tt>uplevel</tt></strong></a> command for more information on what stack
+    levels mean.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info locals</strong> ?<em>pattern</em>?</tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>pattern</em></tt> isn&#8217;t specified, returns a list of all the names
+    of currently-defined local variables, including arguments to the
+    current procedure, if any.  Variables defined with the <a href="#_global"><strong><tt>global</tt></strong></a>
+    and <a href="#_upvar"><strong><tt>upvar</tt></strong></a> commands will not be returned.  If <tt><em>pattern</em></tt> is
+    specified, only those names matching <tt><em>pattern</em></tt> are returned.
+    Matching is determined using the same rules as for <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info nameofexecutable</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the name of the binary file from which the application
+    was invoked. A full path will be returned, unless the path
+    can&#8217;t be determined, in which case the empty string will be returned.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info procs</strong> ?<em>pattern</em>?</tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>pattern</em></tt> isn&#8217;t specified, returns a list of all the
+    names of Tcl command procedures.
+    If <tt><em>pattern</em></tt> is specified, only those names matching <tt><em>pattern</em></tt>
+    are returned.  Matching is determined using the same rules as for
+    <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info references</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns a list of all references which have not yet been garbage
+    collected.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info returncodes</strong> ?<em>code</em>?</tt>
+</dt>
+<dd>
+<p>
+    Returns a list representing the mapping of standard return codes
+    to names. e.g. <tt>{0 ok 1 error 2 return ...}</tt>. If a code is given,
+    instead returns the name for the given code.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info script</strong></tt>
+</dt>
+<dd>
+<p>
+    If a Tcl script file is currently being evaluated (i.e. there is a
+    call to <em>Jim_EvalFile</em> active or there is an active invocation
+    of the <a href="#_source"><strong><tt>source</tt></strong></a> command), then this command returns the name
+    of the innermost file being processed.  Otherwise the command returns an
+    empty string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info source</strong> <em>script</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the original source location of the given script as a list of
+    <tt>{filename linenumber}</tt>. If the source location can&#8217;t be determined, the
+    list <tt>{{} 0}</tt> is returned.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info stacktrace</strong></tt>
+</dt>
+<dd>
+<p>
+    After an error is caught with <a href="#_catch"><strong><tt>catch</tt></strong></a>, returns the stack trace as a list
+    of <tt>{procedure filename line ...}</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info statics</strong> <em>procname</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a dictionary of the static variables of procedure
+    <tt><em>procname</em></tt>.  <tt><em>procname</em></tt> must be the name of a Tcl command
+    procedure. An empty dictionary is returned if the procedure has
+    no static variables.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info version</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the version number for this version of Jim in the form <tt><strong>x.yy</strong></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>info vars</strong> ?<em>pattern</em>?</tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>pattern</em></tt> isn&#8217;t specified,
+    returns a list of all the names of currently-visible variables, including
+    both locals and currently-visible globals.
+    If <tt><em>pattern</em></tt> is specified, only those names matching <tt><em>pattern</em></tt>
+    are returned.  Matching is determined using the same rules as for
+    <a href="#_string"><strong><tt>string</tt></strong></a> <tt>match</tt>.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_join">join</h3>
+<div class="paragraph"><p><tt><strong>join</strong> <em>list ?joinString?</em></tt></p></div>
+<div class="paragraph"><p>The <tt><em>list</em></tt> argument must be a valid Tcl list.  This command returns the
+string formed by joining all of the elements of <tt><em>list</em></tt> together with
+<tt><em>joinString</em></tt> separating each adjacent pair of elements.</p></div>
+<div class="paragraph"><p>The <tt><em>joinString</em></tt> argument defaults to a space character.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_kill">kill</h3>
+<div class="paragraph"><p><tt><strong>kill</strong> ?<em>SIG</em>|<strong>-0</strong>? <em>pid</em></tt></p></div>
+<div class="paragraph"><p>Sends the given signal to the process identified by <tt><em>pid</em></tt>.</p></div>
+<div class="paragraph"><p>The signal may be specified by name or number in one of the following forms:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<tt>TERM</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>SIGTERM</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>-TERM</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>15</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>-15</tt>
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>The signal name may be in either upper or lower case.</p></div>
+<div class="paragraph"><p>The special signal name <tt>-0</tt> simply checks that a signal <tt><em>could</em></tt> be sent.</p></div>
+<div class="paragraph"><p>If no signal is specified, SIGTERM is used.</p></div>
+<div class="paragraph"><p>An error is raised if the signal could not be delivered.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lambda_2">lambda</h3>
+<div class="paragraph"><p><tt><strong>lambda</strong> <em>args ?statics? body</em></tt></p></div>
+<div class="paragraph"><p>The <a href="#_lambda"><strong><tt>lambda</tt></strong></a> command is identical to <a href="#_proc"><strong><tt>proc</tt></strong></a>, except rather than
+creating a named procedure, it creates an anonymous procedure and returns
+the name of the procedure.</p></div>
+<div class="paragraph"><p>See <a href="#_proc"><strong><tt>proc</tt></strong></a> and GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lappend">lappend</h3>
+<div class="paragraph"><p><tt><strong>lappend</strong> <em>varName value ?value value ...?</em></tt></p></div>
+<div class="paragraph"><p>Treat the variable given by <tt><em>varName</em></tt> as a list and append each of
+the <tt><em>value</em></tt> arguments to that list as a separate element, with spaces
+between elements.</p></div>
+<div class="paragraph"><p>If <tt><em>varName</em></tt> doesn&#8217;t exist, it is created as a list with elements given
+by the <tt><em>value</em></tt> arguments. <a href="#_lappend"><strong><tt>lappend</tt></strong></a> is similar to <a href="#_append"><strong><tt>append</tt></strong></a> except that
+each <tt><em>value</em></tt> is appended as a list element rather than raw text.</p></div>
+<div class="paragraph"><p>This command provides a relatively efficient way to build up large lists.
+For example,</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>lappend a $b</tt></pre>
+</div></div>
+<div class="paragraph"><p>is much more efficient than</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a [concat $a [list $b]]</tt></pre>
+</div></div>
+<div class="paragraph"><p>when <tt>$a</tt> is long.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lassign">lassign</h3>
+<div class="paragraph"><p><tt><strong>lassign</strong> <em>list varName ?varName ...?</em></tt></p></div>
+<div class="paragraph"><p>This command treats the value <tt><em>list</em></tt> as a list and assigns successive elements from that list to
+the variables given by the <tt><em>varName</em></tt> arguments in order. If there are more variable names than
+list elements, the remaining variables are set to the empty string. If there are more list ele-
+ments than variables, a list of unassigned elements is returned.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; lassign {1 2 3} a b; puts a=$a,b=$b
+3
+a=1,b=2</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_local">local</h3>
+<div class="paragraph"><p><tt><strong>local</strong> <em>cmd ?arg...?</em></tt></p></div>
+<div class="paragraph"><p>First, <a href="#_local"><strong><tt>local</tt></strong></a> evaluates <tt><em>cmd</em></tt> with the given arguments. The return value must
+be the name of an existing command, which is marked as having local scope.
+This means that when the current procedure exits, the specified
+command is deleted. This can be useful with <a href="#_lambda"><strong><tt>lambda</tt></strong></a>, local procedures or
+to automatically close a filehandle.</p></div>
+<div class="paragraph"><p>In addition, if a command already exists with the same name,
+the existing command will be kept rather than deleted, and may be called
+via <a href="#_upcall"><strong><tt>upcall</tt></strong></a>. The previous command will be restored when the current
+procedure exits. See <a href="#_upcall"><strong><tt>upcall</tt></strong></a> for more details.</p></div>
+<div class="paragraph"><p>In this example, a local procedure is created. Note that the procedure
+continues to have global scope while it is active.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>proc outer {} {
+  # proc ... returns "inner" which is marked local
+  local proc inner {} {
+    # will be deleted when 'outer' exits
+  }</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>  inner
+  ...
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>In this example, the lambda is deleted at the end of the procedure rather
+than waiting until garbage collection.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>proc outer {} {
+  set x [lambda inner {args} {
+    # will be deleted when 'outer' exits
+  }]
+  # Use 'function' here which simply returns $x
+  local function $x</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>  $x ...
+  ...
+}</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_loop">loop</h3>
+<div class="paragraph"><p><tt><strong>loop</strong> <em>var first limit ?incr? body</em></tt></p></div>
+<div class="paragraph"><p>Similar to <a href="#_for"><strong><tt>for</tt></strong></a> except simpler and possibly more efficient.
+With a positive increment, equivalent to:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>for {set var $first} {$var &lt; $limit} {incr var $incr} $body</tt></pre>
+</div></div>
+<div class="paragraph"><p>If <tt><em>incr</em></tt> is not specified, 1 is used.
+Note that setting the loop variable inside the loop does not
+affect the loop count.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lindex">lindex</h3>
+<div class="paragraph"><p><tt><strong>lindex</strong> <em>list index</em></tt></p></div>
+<div class="paragraph"><p>Treats <tt><em>list</em></tt> as a Tcl list and returns element <tt><em>index</em></tt> from it
+(0 refers to the first element of the list).
+See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>index</em></tt>.</p></div>
+<div class="paragraph"><p>In extracting the element, <tt><em>lindex</em></tt> observes the same rules concerning
+braces and quotes and backslashes as the Tcl command interpreter; however,
+variable substitution and command substitution do not occur.</p></div>
+<div class="paragraph"><p>If <tt><em>index</em></tt> is negative or greater than or equal to the number of elements
+in <tt><em>value</em></tt>, then an empty string is returned.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_linsert">linsert</h3>
+<div class="paragraph"><p><tt><strong>linsert</strong> <em>list index element ?element element ...?</em></tt></p></div>
+<div class="paragraph"><p>This command produces a new list from <tt><em>list</em></tt> by inserting all
+of the <tt><em>element</em></tt> arguments just before the element <tt><em>index</em></tt>
+of <tt><em>list</em></tt>. Each <tt><em>element</em></tt> argument will become
+a separate element of the new list. If <tt><em>index</em></tt> is less than
+or equal to zero, then the new elements are inserted at the
+beginning of the list. If <tt><em>index</em></tt> is greater than or equal
+to the number of elements in the list, then the new elements are
+appended to the list.</p></div>
+<div class="paragraph"><p>See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>index</em></tt>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_list">list</h3>
+<div class="paragraph"><p><tt><strong>list</strong> <em>arg ?arg ...?</em></tt></p></div>
+<div class="paragraph"><p>This command returns a list comprised of all the arguments, <tt><em>arg</em></tt>. Braces
+and backslashes get added as necessary, so that the <a href="#_lindex"><strong><tt>lindex</tt></strong></a> command
+may be used on the result to re-extract the original arguments, and also
+so that <a href="#_eval"><strong><tt>eval</tt></strong></a> may be used to execute the resulting list, with
+<tt><em>arg1</em></tt> comprising the command&#8217;s name and the other args comprising
+its arguments. <a href="#_list"><strong><tt>list</tt></strong></a> produces slightly different results than
+<a href="#_concat"><strong><tt>concat</tt></strong></a>:  <a href="#_concat"><strong><tt>concat</tt></strong></a> removes one level of grouping before forming
+the list, while <a href="#_list"><strong><tt>list</tt></strong></a> works directly from the original arguments.
+For example, the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>list a b {c d e} {f {g h}}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>a b {c d e} {f {g h}}</tt></pre>
+</div></div>
+<div class="paragraph"><p>while <a href="#_concat"><strong><tt>concat</tt></strong></a> with the same arguments will return</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>a b c d e f {g h}</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_llength">llength</h3>
+<div class="paragraph"><p><tt><strong>llength</strong> <em>list</em></tt></p></div>
+<div class="paragraph"><p>Treats <tt><em>list</em></tt> as a list and returns a decimal string giving
+the number of elements in it.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lset">lset</h3>
+<div class="paragraph"><p><tt><strong>lset</strong> <em>varName ?index ..? newValue</em></tt></p></div>
+<div class="paragraph"><p>Sets an element in a list.</p></div>
+<div class="paragraph"><p>The <a href="#_lset"><strong><tt>lset</tt></strong></a> command accepts a parameter, <tt><em>varName</em></tt>, which it interprets
+as the name of a variable containing a Tcl list. It also accepts
+zero or more indices into the list. Finally, it accepts a new value
+for an element of varName. If no indices are presented, the command
+takes the form:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>lset varName newValue</tt></pre>
+</div></div>
+<div class="paragraph"><p>In this case, newValue replaces the old value of the variable
+varName.</p></div>
+<div class="paragraph"><p>When presented with a single index, the <a href="#_lset"><strong><tt>lset</tt></strong></a> command
+treats the content of the varName variable as a Tcl list. It addresses
+the index&#8217;th element in it (0 refers to the first element of the
+list). When interpreting the list, <a href="#_lset"><strong><tt>lset</tt></strong></a> observes the same rules
+concerning braces and quotes and backslashes as the Tcl command
+interpreter; however, variable substitution and command substitution
+do not occur. The command constructs a new list in which the
+designated element is replaced with newValue. This new list is
+stored in the variable varName, and is also the return value from
+the <a href="#_lset"><strong><tt>lset</tt></strong></a> command.</p></div>
+<div class="paragraph"><p>If index is negative or greater than or equal to the number of
+elements in $varName, then an error occurs.</p></div>
+<div class="paragraph"><p>See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>index</em></tt>.</p></div>
+<div class="paragraph"><p>If additional index arguments are supplied, then each argument is
+used in turn to address an element within a sublist designated by
+the previous indexing operation, allowing the script to alter
+elements in sublists. The command,</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>lset a 1 2 newValue</tt></pre>
+</div></div>
+<div class="paragraph"><p>replaces element 2 of sublist 1 with <tt><em>newValue</em></tt>.</p></div>
+<div class="paragraph"><p>The integer appearing in each index argument must be greater than
+or equal to zero. The integer appearing in each index argument must
+be strictly less than the length of the corresponding list. In other
+words, the <a href="#_lset"><strong><tt>lset</tt></strong></a> command cannot change the size of a list. If an
+index is outside the permitted range, an error is reported.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lmap">lmap</h3>
+<div class="paragraph"><p><tt><strong>lmap</strong> <em>varName list body</em></tt></p></div>
+<div class="paragraph"><p><tt><strong>lmap</strong> <em>varList list ?varList2 list2 ...? body</em></tt></p></div>
+<div class="paragraph"><p><a href="#_lmap"><strong><tt>lmap</tt></strong></a> is a "collecting" <a href="#_foreach"><strong><tt>foreach</tt></strong></a> which returns a list of its results.</p></div>
+<div class="paragraph"><p>For example:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; lmap i {1 2 3 4 5} {expr $i*$i}
+1 4 9 16 25
+jim&gt; lmap a {1 2 3} b {A B C} {list $a $b}
+{1 A} {2 B} {3 C}</tt></pre>
+</div></div>
+<div class="paragraph"><p>If the body invokes <a href="#_continue"><strong><tt>continue</tt></strong></a>, no value is added for this iteration.
+If the body invokes <a href="#_break"><strong><tt>break</tt></strong></a>, the loop ends and no more values are added.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_load">load</h3>
+<div class="paragraph"><p><tt><strong>load</strong> <em>filename</em></tt></p></div>
+<div class="paragraph"><p>Loads the dynamic extension, <tt><em>filename</em></tt>. Generally the filename should have
+the extension <tt>.so</tt>. The initialisation function for the module must be based
+on the name of the file. For example loading <tt>hwaccess.so</tt> will invoke
+the initialisation function, <tt>Jim_hwaccessInit</tt>. Normally the <a href="#_load"><strong><tt>load</tt></strong></a> command
+should not be used directly. Instead it is invoked automatically by <a href="#_package"><strong><tt>package</tt></strong></a> <tt>require</tt>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lrange">lrange</h3>
+<div class="paragraph"><p><tt><strong>lrange</strong> <em>list first last</em></tt></p></div>
+<div class="paragraph"><p><tt><em>list</em></tt> must be a valid Tcl list. This command will return a new
+list consisting of elements <tt><em>first</em></tt> through <tt><em>last</em></tt>, inclusive.</p></div>
+<div class="paragraph"><p>See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>first</em></tt> and <tt><em>last</em></tt>.</p></div>
+<div class="paragraph"><p>If <tt><em>last</em></tt> is greater than or equal to the number of elements
+in the list, then it is treated as if it were <tt>end</tt>.</p></div>
+<div class="paragraph"><p>If <tt><em>first</em></tt> is greater than <tt><em>last</em></tt> then an empty string
+is returned.</p></div>
+<div class="paragraph"><p>Note: <tt>"<a href="#_lrange"><strong><tt>lrange</tt></strong></a> <em>list first first</em>"</tt> does not always produce the
+same result as <tt>"<a href="#_lindex"><strong><tt>lindex</tt></strong></a> <em>list first</em>"</tt> (although it often does
+for simple fields that aren&#8217;t enclosed in braces); it does, however,
+produce exactly the same results as <tt>"<a href="#_list"><strong><tt>list</tt></strong></a> [<a href="#_lindex"><strong><tt>lindex</tt></strong></a> <em>list first</em>]"</tt></p></div>
+</div>
+<div class="sect2">
+<h3 id="_lreplace">lreplace</h3>
+<div class="paragraph"><p><tt><strong>lreplace</strong> <em>list first last ?element element ...?</em></tt></p></div>
+<div class="paragraph"><p>Returns a new list formed by replacing one or more elements of
+<tt><em>list</em></tt> with the <tt><em>element</em></tt> arguments.</p></div>
+<div class="paragraph"><p><tt><em>first</em></tt> gives the index in <tt><em>list</em></tt> of the first element
+to be replaced.</p></div>
+<div class="paragraph"><p>If <tt><em>first</em></tt> is less than zero then it refers to the first
+element of <tt><em>list</em></tt>;  the element indicated by <tt><em>first</em></tt>
+must exist in the list.</p></div>
+<div class="paragraph"><p><tt><em>last</em></tt> gives the index in <tt><em>list</em></tt> of the last element
+to be replaced;  it must be greater than or equal to <tt><em>first</em></tt>.</p></div>
+<div class="paragraph"><p>See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>first</em></tt> and <tt><em>last</em></tt>.</p></div>
+<div class="paragraph"><p>The <tt><em>element</em></tt> arguments specify zero or more new arguments to
+be added to the list in place of those that were deleted.</p></div>
+<div class="paragraph"><p>Each <tt><em>element</em></tt> argument will become a separate element of
+the list.</p></div>
+<div class="paragraph"><p>If no <tt><em>element</em></tt> arguments are specified, then the elements
+between <tt><em>first</em></tt> and <tt><em>last</em></tt> are simply deleted.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_lrepeat">lrepeat</h3>
+<div class="paragraph"><p><tt><strong>lrepeat</strong> <em>number element1 ?element2 ...?</em></tt></p></div>
+<div class="paragraph"><p>Build a list by repeating elements <tt><em>number</em></tt> times (which must be
+a positive integer).</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; lrepeat 3 a b
+a b a b a b</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_lreverse">lreverse</h3>
+<div class="paragraph"><p><tt><strong>lreverse</strong> <em>list</em></tt></p></div>
+<div class="paragraph"><p>Returns the list in reverse order.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; lreverse {1 2 3}
+3 2 1</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_lsearch">lsearch</h3>
+<div class="paragraph"><p><tt><strong>lsearch</strong> <em>?options? list pattern</em></tt></p></div>
+<div class="paragraph"><p>This command searches the elements <tt><em>list</em></tt> to see if one of them matches <tt><em>pattern</em></tt>. If so, the
+command returns the index of the first matching element (unless the options <tt>-all</tt>, <tt>-inline</tt> or <tt>-bool</tt> are
+specified.) If not, the command returns -1. The option arguments indicates how the elements of
+the list are to be matched against pattern and must have one of the values below:</p></div>
+<div class="paragraph"><p><strong>Note</strong> that this command is different from Tcl in that default match type is <tt>-exact</tt> rather than <tt>-glob</tt>.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>-exact</strong></tt>
+</dt>
+<dd>
+<p>
+    <tt><em>pattern</em></tt> is a literal string that is compared for exact equality against each list element.
+    This is the default.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-glob</strong></tt>
+</dt>
+<dd>
+<p>
+    <tt><em>pattern</em></tt> is a glob-style pattern which is matched against each list element using the same
+    rules as the string match command.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-regexp</strong></tt>
+</dt>
+<dd>
+<p>
+    <tt><em>pattern</em></tt> is treated as a regular expression and matched against each list element using
+    the rules described by <a href="#_regexp"><strong><tt>regexp</tt></strong></a>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-command</strong> <em>cmdname</em></tt>
+</dt>
+<dd>
+<p>
+    <tt><em>cmdname</em></tt> is a command which is used to match the pattern against each element of the
+    list. It is invoked as <tt><em>cmdname</em> ?<strong>-nocase</strong>? <em>pattern listvalue</em></tt> and should return 1
+    for a match, or 0 for no match.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-all</strong></tt>
+</dt>
+<dd>
+<p>
+    Changes the result to be the list of all matching indices (or all matching values if
+    <tt>-inline</tt> is specified as well). If indices are returned, the indices will be in numeric
+    order. If values are returned, the order of the values will be the order of those values
+    within the input list.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-inline</strong></tt>
+</dt>
+<dd>
+<p>
+    The matching value is returned instead of its index (or an empty string if no value
+    matches). If <tt>-all</tt> is also specified, then the result of the command is the list of all
+    values that matched. The <tt>-inline</tt> and <tt>-bool</tt> options are mutually exclusive.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-bool</strong></tt>
+</dt>
+<dd>
+<p>
+    Changes the result to <em>1</em> if a match was found, or <em>0</em> otherwise. If <tt>-all</tt> is also specified,
+    the result will be a list of <em>0</em> and <em>1</em> for each element of the list depending upon whether
+    the corresponding element matches. The <tt>-inline</tt> and <tt>-bool</tt> options are mutually exclusive.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-not</strong></tt>
+</dt>
+<dd>
+<p>
+    This negates the sense of the match, returning the index (or value
+    if <tt>-inline</tt> is specified) of the first non-matching value in the
+    list. If <tt>-bool</tt> is also specified, the <em>0</em> will be returned if a
+    match is found, or <em>1</em> otherwise. If <tt>-all</tt> is also specified,
+    non-matches will be returned rather than matches.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-nocase</strong></tt>
+</dt>
+<dd>
+<p>
+    Causes comparisons to be handled in a case-insensitive manner.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_lsort">lsort</h3>
+<div class="paragraph"><p><tt><strong>lsort</strong> ?<strong>-index</strong> <em>listindex</em>? ?<strong>-nocase!-integer|-real|-command</strong> <em>cmdname</em>? ?<strong>-unique</strong>? ?<strong>-decreasing</strong>|<strong>-increasing</strong>? <em>list</em></tt></p></div>
+<div class="paragraph"><p>Sort the elements of <tt><em>list</em></tt>, returning a new list in sorted order.
+By default, ASCII (or UTF-8) sorting is used, with the result in increasing order.</p></div>
+<div class="paragraph"><p>If <tt>-nocase</tt> is specified, comparisons are case-insenstive.</p></div>
+<div class="paragraph"><p>If <tt>-integer</tt> is specified, numeric sorting is used.</p></div>
+<div class="paragraph"><p>If <tt>-real</tt> is specified, floating point number sorting is used.</p></div>
+<div class="paragraph"><p>If <tt>-command <em>cmdname</em></tt> is specified, <tt><em>cmdname</em></tt> is treated as a command
+name. For each comparison, <tt><em>cmdname $value1 $value2</tt></em> is called which
+should compare the values and return an integer less than, equal
+to, or greater than zero if the <tt><em>$value1</em></tt> is to be considered less
+than, equal to, or greater than <tt><em>$value2</em></tt>, respectively.</p></div>
+<div class="paragraph"><p>If <tt>-decreasing</tt> is specified, the resulting list is in the opposite
+order to what it would be otherwise. <tt>-increasing</tt> is the default.</p></div>
+<div class="paragraph"><p>If <tt>-unique</tt> is specified, then only the last set of duplicate elements found in the list will be retained.
+Note that duplicates are determined relative to the comparison used in the sort. Thus if <tt>-index 0</tt> is used,
+<tt>{1 a}</tt> and <tt>{1 b}</tt> would be considered duplicates and only the second element, <tt>{1 b}</tt>, would be retained.</p></div>
+<div class="paragraph"><p>If <tt>-index <em>listindex</em></tt> is specified, each element of the list is treated as a list and
+the given index is extracted from the list for comparison. The list index may
+be any valid list index, such as <tt>1</tt>, <tt>end</tt> or <tt>end-2</tt>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_open">open</h3>
+<div class="paragraph"><p><tt><strong>open</strong> <em>fileName ?access?</em></tt></p></div>
+<div class="paragraph"><p><tt><strong>open</strong> <em>|command-pipeline ?access?</em></tt></p></div>
+<div class="paragraph"><p>Opens a file and returns an identifier
+that may be used in future invocations
+of commands like <a href="#_read"><strong><tt>read</tt></strong></a>, <a href="#_puts"><strong><tt>puts</tt></strong></a>, and <a href="#_close"><strong><tt>close</tt></strong></a>.
+<tt><em>fileName</em></tt> gives the name of the file to open.</p></div>
+<div class="paragraph"><p>The <tt><em>access</em></tt> argument indicates the way in which the file is to be accessed.
+It may have any of the following values:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>r</tt>
+</dt>
+<dd>
+<p>
+    Open the file for reading only; the file must already exist.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>r</tt>+
+</dt>
+<dd>
+<p>
+    Open the file for both reading and writing; the file must
+    already exist.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>w</tt>
+</dt>
+<dd>
+<p>
+    Open the file for writing only. Truncate it if it exists. If it doesn&#8217;t
+    exist, create a new file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>w</tt>+
+</dt>
+<dd>
+<p>
+    Open the file for reading and writing. Truncate it if it exists.
+    If it doesn&#8217;t exist, create a new file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>a</tt>
+</dt>
+<dd>
+<p>
+    Open the file for writing only. The file must already exist, and the file
+    is positioned so that new data is appended to the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>a</tt>+
+</dt>
+<dd>
+<p>
+    Open the file for reading and writing. If the file doesn&#8217;t
+    exist, create a new empty file. Set the initial access position
+    to the end of the file.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p><tt><em>access</em></tt> defaults to <em>r</em>.</p></div>
+<div class="paragraph"><p>If a file is opened for both reading and writing, then <a href="#_seek"><strong><tt>seek</tt></strong></a>
+must be invoked between a read and a write, or vice versa.</p></div>
+<div class="paragraph"><p>If the first character of <tt><em>fileName</em></tt> is "|" then the remaining
+characters of <tt><em>fileName</em></tt> are treated as a list of arguments that
+describe a command pipeline to invoke, in the same style as the
+arguments for exec. In this case, the channel identifier returned
+by open may be used to write to the command&#8217;s input pipe or read
+from its output pipe, depending on the value of <tt><em>access</em></tt>. If write-only
+access is used (e.g. <tt><em>access</em></tt> is <em>w</em>), then standard output for the
+pipeline is directed to the current standard output unless overridden
+by the command. If read-only access is used (e.g. <tt><em>access</em></tt> is r),
+standard input for the pipeline is taken from the current standard
+input unless overridden by the command.</p></div>
+<div class="paragraph"><p>The <a href="#_pid"><strong><tt>pid</tt></strong></a> command may be used to return the process ids of the commands
+forming the command pipeline.</p></div>
+<div class="paragraph"><p>See also <a href="#_socket"><strong><tt>socket</tt></strong></a>, <a href="#_pid"><strong><tt>pid</tt></strong></a>, <a href="#_exec"><strong><tt>exec</tt></strong></a></p></div>
+</div>
+<div class="sect2">
+<h3 id="_package">package</h3>
+<div class="paragraph"><p><tt><strong>package provide</strong> <em>name ?version?</em></tt></p></div>
+<div class="paragraph"><p>Indicates that the current script provides the package named <tt><em>name</em></tt>.
+If no version is specified, <em>1.0</em> is used.</p></div>
+<div class="paragraph"><p>Any script which provides a package may include this statement
+as the first statement, although it is not required.</p></div>
+<div class="paragraph"><p><tt><strong>package require</strong> <em>name ?version?</em>*</tt></p></div>
+<div class="paragraph"><p>Searches for the package with the given <tt><em>name</em></tt> by examining each path
+in <em>$::auto_path</em> and trying to load <em>$path/$name.so</em> as a dynamic extension,
+or <em>$path/$name.tcl</em> as a script package.</p></div>
+<div class="paragraph"><p>The first such file which is found is considered to provide the the package.
+(The version number is ignored).</p></div>
+<div class="paragraph"><p>If <em>$name.so</em> exists, it is loaded with the <a href="#_load"><strong><tt>load</tt></strong></a> command,
+otherwise if <em>$name.tcl</em> exists it is loaded with the <a href="#_source"><strong><tt>source</tt></strong></a> command.</p></div>
+<div class="paragraph"><p>If <a href="#_load"><strong><tt>load</tt></strong></a> or <a href="#_source"><strong><tt>source</tt></strong></a> fails, <a href="#_package"><strong><tt>package</tt></strong></a> <tt>require</tt> will fail immediately.
+No further attempt will be made to locate the file.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_pid">pid</h3>
+<div class="paragraph"><p><tt><strong>pid</strong></tt></p></div>
+<div class="paragraph"><p><tt><strong>pid</strong> <em>fileId</em></tt></p></div>
+<div class="paragraph"><p>The first form returns the process identifier of the current process.</p></div>
+<div class="paragraph"><p>The second form accepts a handle returned by <a href="#_open"><strong><tt>open</tt></strong></a> and returns a list
+of the process ids forming the pipeline in the same form as <a href="#_exec"><strong><tt>exec</tt></strong></a> <tt>... &amp;</tt>.
+If <em>fileId</em> represents a regular file handle rather than a command pipeline,
+the empty string is returned instead.</p></div>
+<div class="paragraph"><p>See also <a href="#_open"><strong><tt>open</tt></strong></a>, <a href="#_exec"><strong><tt>exec</tt></strong></a></p></div>
+</div>
+<div class="sect2">
+<h3 id="_proc">proc</h3>
+<div class="paragraph"><p><tt><strong>proc</strong> <em>name args ?statics? body</em></tt></p></div>
+<div class="paragraph"><p>The <a href="#_proc"><strong><tt>proc</tt></strong></a> command creates a new Tcl command procedure, <tt><em>name</em></tt>.
+When the new command is invoked, the contents of <tt><em>body</em></tt> will be executed.
+Tcl interpreter. <tt><em>args</em></tt> specifies the formal arguments to the procedure.
+If specified, <tt><em>static</em></tt>, declares static variables which are bound to the
+procedure.</p></div>
+<div class="paragraph"><p>See PROCEDURES for detailed information about Tcl procedures.</p></div>
+<div class="paragraph"><p>The <a href="#_proc"><strong><tt>proc</tt></strong></a> command returns <tt><em>name</em></tt> (which is useful with <a href="#_local"><strong><tt>local</tt></strong></a>).</p></div>
+<div class="paragraph"><p>When a procedure is invoked, the procedure&#8217;s return value is the
+value specified in a <a href="#_return"><strong><tt>return</tt></strong></a> command.  If the procedure doesn&#8217;t
+execute an explicit <a href="#_return"><strong><tt>return</tt></strong></a>, then its return value is the value
+of the last command executed in the procedure&#8217;s body.</p></div>
+<div class="paragraph"><p>If an error occurs while executing the procedure body, then the
+procedure-as-a-whole will return that same error.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_puts">puts</h3>
+<div class="paragraph"><p><tt><strong>puts</strong> ?<strong>-nonewline</strong>? <em>?fileId? string</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>puts</strong> ?<strong>-nonewline</strong>? <em>string</em></tt></p></div>
+<div class="paragraph"><p>Writes the characters given by <tt><em>string</em></tt> to the file given
+by <tt><em>fileId</em></tt>. <tt><em>fileId</em></tt> must have been the return
+value from a previous call to <a href="#_open"><strong><tt>open</tt></strong></a>, or it may be
+<tt>stdout</tt> or <tt>stderr</tt> to refer to one of the standard I/O
+channels; it must refer to a file that was opened for
+writing.</p></div>
+<div class="paragraph"><p>In the first form, if no <tt><em>fileId</em></tt> is specified then it defaults to <tt>stdout</tt>.
+<a href="#_puts"><strong><tt>puts</tt></strong></a> normally outputs a newline character after <tt><em>string</em></tt>,
+but this feature may be suppressed by specifying the <tt>-nonewline</tt>
+switch.</p></div>
+<div class="paragraph"><p>Output to files is buffered internally by Tcl; the <a href="#_flush"><strong><tt>flush</tt></strong></a>
+command may be used to force buffered characters to be output.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_pwd">pwd</h3>
+<div class="paragraph"><p><tt><strong>pwd</strong></tt></p></div>
+<div class="paragraph"><p>Returns the path name of the current working directory.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_rand">rand</h3>
+<div class="paragraph"><p><tt><strong>rand</strong> <em>?min? ?max?</em></tt></p></div>
+<div class="paragraph"><p>Returns a random integer between <tt><em>min</em></tt> (defaults to 0) and <tt><em>max</em></tt>
+(defaults to the maximum integer).</p></div>
+<div class="paragraph"><p>If only one argument is given, it is interpreted as <tt><em>max</em></tt>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_range">range</h3>
+<div class="paragraph"><p><tt><strong>range</strong> <em>?start? end ?step?</em></tt></p></div>
+<div class="paragraph"><p>Returns a list of integers starting at <tt><em>start</em></tt> (defaults to 0)
+and ranging up to but not including <tt><em>end</em></tt> in steps of <tt><em>step</em></tt> defaults to 1).</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; range 5
+0 1 2 3 4
+jim&gt; range 2 5
+2 3 4
+jim&gt; range 2 10 4
+2 6
+jim&gt; range 7 4 -2
+7 5</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_read">read</h3>
+<div class="paragraph"><p><tt><strong>read</strong> ?<strong>-nonewline</strong>? <em>fileId</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>read</strong> ?<strong>-nonewline</strong>?</tt></p></div>
+<div class="paragraph"><p><tt><strong>read</strong> <em>fileId numBytes</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>read</strong> <em>numBytes</em></tt></p></div>
+<div class="paragraph"><p>In the first form, all of the remaining bytes are read from the file
+given by <tt><em>fileId</em></tt>; they are returned as the result of the command.
+If the <tt>-nonewline</tt> switch is specified then the last
+character of the file is discarded if it is a newline.</p></div>
+<div class="paragraph"><p>In the second form, the extra argument specifies how many bytes to read;
+exactly this many bytes will be read and returned, unless there are fewer than
+<tt><em>numBytes</em></tt> bytes left in the file; in this case, all the remaining
+bytes are returned.</p></div>
+<div class="paragraph"><p><tt><em>fileId</em></tt> must be <tt>stdin</tt> or the return value from a previous call
+to <a href="#_open"><strong><tt>open</tt></strong></a>; it must refer to a file that was opened for reading.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_regexp">regexp</h3>
+<div class="paragraph"><p><tt><strong>regexp ?-nocase? ?-line? ?-indices? ?-start</strong> <em>offset</em>? <strong>?-all? ?-inline? ?--?</strong> <em>exp string ?matchVar? ?subMatchVar subMatchVar ...?</em></tt></p></div>
+<div class="paragraph"><p>Determines whether the regular expression <tt><em>exp</em></tt> matches part or
+all of <tt><em>string</em></tt> and returns 1 if it does, 0 if it doesn&#8217;t.</p></div>
+<div class="paragraph"><p>See REGULAR EXPRESSIONS above for complete information on the
+syntax of <tt><em>exp</em></tt> and how it is matched against <tt><em>string</em></tt>.</p></div>
+<div class="paragraph"><p>If additional arguments are specified after <tt><em>string</em></tt> then they
+are treated as the names of variables to use to return
+information about which part(s) of <tt><em>string</em></tt> matched <tt><em>exp</em></tt>.
+<tt><em>matchVar</em></tt> will be set to the range of <tt><em>string</em></tt> that
+matched all of <tt><em>exp</em></tt>. The first <tt><em>subMatchVar</em></tt> will contain
+the characters in <tt><em>string</em></tt> that matched the leftmost parenthesized
+subexpression within <tt><em>exp</em></tt>, the next <tt><em>subMatchVar</em></tt> will
+contain the characters that matched the next parenthesized
+subexpression to the right in <tt><em>exp</em></tt>, and so on.</p></div>
+<div class="paragraph"><p>Normally, <tt><em>matchVar</em></tt> and the each <tt><em>subMatchVar</em></tt> are set to hold the
+matching characters from <a href="#_string"><strong><tt>string</tt></strong></a>, however see <tt>-indices</tt> and
+<tt>-inline</tt> below.</p></div>
+<div class="paragraph"><p>If there are more values for <tt><em>subMatchVar</em></tt> than parenthesized subexpressions
+within <tt><em>exp</em></tt>, or if a particular subexpression in <tt><em>exp</em></tt> doesn&#8217;t
+match the string (e.g. because it was in a portion of the expression
+that wasn&#8217;t matched), then the corresponding <tt><em>subMatchVar</em></tt> will be
+set to <tt>"-1 -1"</tt> if <tt>-indices</tt> has been specified or to an empty
+string otherwise.</p></div>
+<div class="paragraph"><p>The following switches modify the behaviour of <tt><em>regexp</em></tt></p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>-nocase</strong></tt>
+</dt>
+<dd>
+<p>
+    Causes upper-case and lower-case characters to be treated as
+    identical during the matching process.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-line</strong></tt>
+</dt>
+<dd>
+<p>
+    Use newline-sensitive matching. By default, newline
+    is a completely ordinary character with no special meaning in
+    either REs or strings. With this flag, <tt>[<sup></tt> bracket expressions
+    and <tt>.</tt> never match newline, a <tt></sup></tt> anchor matches the null
+    string after any newline in the string in addition to its normal
+    function, and the <tt>$</tt> anchor matches the null string before any
+    newline in the string in addition to its normal function.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-indices</strong></tt>
+</dt>
+<dd>
+<p>
+    Changes what is stored in the subMatchVars. Instead of
+    storing the matching characters from string, each variable
+    will contain a list of two decimal strings giving the indices
+    in string of the first and last characters in the matching
+    range of characters.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-start</strong> <em>offset</em></tt>
+</dt>
+<dd>
+<p>
+    Specifies a character index offset into the string at which to start
+    matching the regular expression. If <tt>-indices</tt> is
+    specified, the indices will be indexed starting from the
+    absolute beginning of the input string. <tt><em>offset</em></tt> will be
+    constrained to the bounds of the input string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-all</strong></tt>
+</dt>
+<dd>
+<p>
+    Causes the regular expression to be matched as many times as possible
+    in the string, returning the total number of matches found. If this
+    is specified with match variables, they will contain information
+    for the last match only.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-inline</strong></tt>
+</dt>
+<dd>
+<p>
+    Causes the command to return, as a list, the data that would otherwise
+    be placed in match variables. When using <tt>-inline</tt>, match variables
+    may not be specified. If used with <tt>-all</tt>, the list will be concatenated
+    at each iteration, such that a flat list is always returned. For
+    each match iteration, the command will append the overall match
+    data, plus one element for each subexpression in the regular
+    expression.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>--</strong></tt>
+</dt>
+<dd>
+<p>
+    Marks the end of switches. The argument following this one will be
+    treated as <tt><em>exp</em></tt> even if it starts with a <tt>-</tt>.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_regsub">regsub</h3>
+<div class="paragraph"><p><tt><strong>regsub ?-nocase? ?-all? ?-line? ?-start</strong> <em>offset</em>? ?<strong>--</strong>? <em>exp string subSpec ?varName?</em></tt></p></div>
+<div class="paragraph"><p>This command matches the regular expression <tt><em>exp</em></tt> against
+<tt><em>string</em></tt> using the rules described in REGULAR EXPRESSIONS
+above.</p></div>
+<div class="paragraph"><p>If <tt><em>varName</em></tt> is specified, the commands stores <tt><em>string</em></tt> to <tt><em>varName</em></tt>
+with the substitutions detailed below, and returns the number of
+substitutions made (normally 1 unless <tt>-all</tt> is specified).
+This is 0 if there were no matches.</p></div>
+<div class="paragraph"><p>If <tt><em>varName</em></tt> is not specified, the substituted string will be returned
+instead.</p></div>
+<div class="paragraph"><p>When copying <tt><em>string</em></tt>, the portion of <tt><em>string</em></tt> that
+matched <tt><em>exp</em></tt> is replaced with <tt><em>subSpec</em></tt>.
+If <tt><em>subSpec</em></tt> contains a <tt>&amp;</tt> or <tt>\0</tt>, then it is replaced
+in the substitution with the portion of <tt><em>string</em></tt> that
+matched <tt><em>exp</em></tt>.</p></div>
+<div class="paragraph"><p>If <tt><em>subSpec</em></tt> contains a <tt>\n</tt>, where <tt><em>n</em></tt> is a digit
+between 1 and 9, then it is replaced in the substitution with
+the portion of <tt><em>string</em></tt> that matched the <tt><em>n</em></tt>'-th
+parenthesized subexpression of <tt><em>exp</em></tt>.
+Additional backslashes may be used in <tt><em>subSpec</em></tt> to prevent special
+interpretation of <tt>&amp;</tt> or <tt>\0</tt> or <tt>\n</tt> or
+backslash.</p></div>
+<div class="paragraph"><p>The use of backslashes in <tt><em>subSpec</em></tt> tends to interact badly
+with the Tcl parser&#8217;s use of backslashes, so it&#8217;s generally
+safest to enclose <tt><em>subSpec</em></tt> in braces if it includes
+backslashes.</p></div>
+<div class="paragraph"><p>The following switches modify the behaviour of <tt><em>regsub</em></tt></p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>-nocase</strong></tt>
+</dt>
+<dd>
+<p>
+    Upper-case characters in <tt><em>string</em></tt> are converted to lower-case
+    before matching against <tt><em>exp</em></tt>;  however, substitutions
+    specified by <tt><em>subSpec</em></tt> use the original unconverted form
+    of <tt><em>string</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-all</strong></tt>
+</dt>
+<dd>
+<p>
+    All ranges in <tt><em>string</em></tt> that match <tt><em>exp</em></tt> are found and substitution
+    is performed for each of these ranges, rather than only the
+    first. The <tt>&amp;</tt> and <tt>\n</tt> sequences are handled for
+    each substitution using the information from the corresponding
+    match.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-line</strong></tt>
+</dt>
+<dd>
+<p>
+    Use newline-sensitive matching. By default, newline
+    is a completely ordinary character with no special meaning in
+    either REs or strings.  With this flag, <tt>[<sup></tt> bracket expressions
+    and <tt>.</tt> never match newline, a <tt></sup></tt> anchor matches the null
+    string after any newline in the string in addition to its normal
+    function, and the <tt>$</tt> anchor matches the null string before any
+    newline in the string in addition to its normal function.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-start</strong> <em>offset</em></tt>
+</dt>
+<dd>
+<p>
+    Specifies a character index offset into the string at which to
+    start matching the regular expression. <tt><em>offset</em></tt> will be
+    constrained to the bounds of the input string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>--</strong></tt>
+</dt>
+<dd>
+<p>
+    Marks the end of switches. The argument following this one will be
+    treated as <tt><em>exp</em></tt> even if it starts with a <tt>-</tt>.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_ref">ref</h3>
+<div class="paragraph"><p><tt><strong>ref</strong> <em>string tag ?finalizer?</em></tt></p></div>
+<div class="paragraph"><p>Create a new reference containing <tt><em>string</em></tt> of type <tt><em>tag</em></tt>.
+If <tt><em>finalizer</em></tt> is specified, it is a command which will be invoked
+when the a garbage collection cycle runs and this reference is
+no longer accessible.</p></div>
+<div class="paragraph"><p>The finalizer is invoked as:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>finalizer reference string</tt></pre>
+</div></div>
+<div class="paragraph"><p>See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_rename">rename</h3>
+<div class="paragraph"><p><tt><strong>rename</strong> <em>oldName newName</em></tt></p></div>
+<div class="paragraph"><p>Rename the command that used to be called <tt><em>oldName</em></tt> so that it
+is now called <tt><em>newName</em></tt>.  If <tt><em>newName</em></tt> is an empty string
+(e.g. {}) then <tt><em>oldName</em></tt> is deleted.  The <a href="#_rename"><strong><tt>rename</tt></strong></a> command
+returns an empty string as result.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_return">return</h3>
+<div class="paragraph"><p><tt><strong>return</strong> ?<strong>-code</strong> <em>code</em>? ?<strong>-errorinfo</strong> <em>stacktrace</em>? ?<strong>-errorcode</strong> <em>errorcode</em>? ?<strong>-level</strong> <em>n</em>? ?<em>value</em>?</tt></p></div>
+<div class="paragraph"><p>Return immediately from the current procedure (or top-level command
+or <a href="#_source"><strong><tt>source</tt></strong></a> command), with <tt><em>value</em></tt> as the return value.  If <tt><em>value</em></tt>
+is not specified, an empty string will be returned as result.</p></div>
+<div class="paragraph"><p>If <tt>-code</tt> is specified (as either a number or ok, error, break,
+continue, signal, return or exit), this code will be used instead
+of <tt>JIM_OK</tt>. This is generally useful when implementing flow of control
+commands.</p></div>
+<div class="paragraph"><p>If <tt>-level</tt> is specified and greater than 1, it has the effect of delaying
+the new return code from <tt>-code</tt>. This is useful when rethrowing an error
+from <a href="#_catch"><strong><tt>catch</tt></strong></a>. See the implementation of try/catch in tclcompat.tcl for
+an example of how this is done.</p></div>
+<div class="paragraph"><p>Note: The following options are only used when <tt>-code</tt> is JIM_ERR.</p></div>
+<div class="paragraph"><p>If <tt>-errorinfo</tt> is specified (as returned from <a href="#_info"><strong><tt>info</tt></strong></a> <tt>stacktrace</tt>)
+it is used to initialize the stacktrace.</p></div>
+<div class="paragraph"><p>If <tt>-errorcode</tt> is specified, it is used to set the global variable $::errorCode.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_scan">scan</h3>
+<div class="paragraph"><p><tt><strong>scan</strong> <em>string format varName1 ?varName2 ...?</em></tt></p></div>
+<div class="paragraph"><p>This command parses fields from an input string in the same fashion
+as the C <em>sscanf</em> procedure.  <tt><em>string</em></tt> gives the input to be parsed
+and <tt><em>format</em></tt> indicates how to parse it, using <em>%</em> fields as in
+<em>sscanf</em>.  All of the <em>sscanf</em> options are valid; see the <em>sscanf</em>
+man page for details.  Each <tt><em>varName</em></tt> gives the name of a variable;
+when a field is scanned from <tt><em>string</em></tt>, the result is converted back
+into a string and assigned to the corresponding <tt><em>varName</em></tt>.  The
+only unusual conversion is for <em>%c</em>.  For <em>%c</em> conversions a single
+character value is converted to a decimal string, which is then
+assigned to the corresponding <tt><em>varName</em></tt>; no field width may be
+specified for this conversion.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_seek">seek</h3>
+<div class="paragraph"><p><tt><strong>seek</strong> <em>fileId offset ?origin?</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>seek</strong> <em>offset ?origin?</em></tt></p></div>
+<div class="paragraph"><p>Change the current access position for <tt><em>fileId</em></tt>.
+The <tt><em>offset</em></tt> and <tt><em>origin</em></tt> arguments specify the position at
+which the next read or write will occur for <tt><em>fileId</em></tt>.
+<tt><em>offset</em></tt> must be a number (which may be negative) and <tt><em>origin</em></tt>
+must be one of the following:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>start</strong></tt>
+</dt>
+<dd>
+<p>
+    The new access position will be <tt><em>offset</em></tt> bytes from the start
+    of the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>current</strong></tt>
+</dt>
+<dd>
+<p>
+    The new access position will be <tt><em>offset</em></tt> bytes from the current
+    access position; a negative <tt><em>offset</em></tt> moves the access position
+    backwards in the file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>end</strong></tt>
+</dt>
+<dd>
+<p>
+    The new access position will be <tt><em>offset</em></tt> bytes from the end of
+    the file.  A negative <tt><em>offset</em></tt> places the access position before
+    the end-of-file, and a positive <tt><em>offset</em></tt> places the access position
+    after the end-of-file.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>The <tt><em>origin</em></tt> argument defaults to <tt>start</tt>.</p></div>
+<div class="paragraph"><p><tt><em>fileId</em></tt> must have been the return value from a previous call to
+<a href="#_open"><strong><tt>open</tt></strong></a>, or it may be <tt>stdin</tt>, <tt>stdout</tt>, or <tt>stderr</tt> to refer to one
+of the standard I/O channels.</p></div>
+<div class="paragraph"><p>This command returns an empty string.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_set">set</h3>
+<div class="paragraph"><p><tt><strong>set</strong> <em>varName ?value?</em></tt></p></div>
+<div class="paragraph"><p>Returns the value of variable <tt><em>varName</em></tt>.</p></div>
+<div class="paragraph"><p>If <tt><em>value</em></tt> is specified, then set the value of <tt><em>varName</em></tt> to <tt><em>value</em></tt>,
+creating a new variable if one doesn&#8217;t already exist, and return
+its value.</p></div>
+<div class="paragraph"><p>If <tt><em>varName</em></tt> contains an open parenthesis and ends with a
+close parenthesis, then it refers to an array element:  the characters
+before the open parenthesis are the name of the array, and the characters
+between the parentheses are the index within the array.
+Otherwise <tt><em>varName</em></tt> refers to a scalar variable.</p></div>
+<div class="paragraph"><p>If no procedure is active, then <tt><em>varName</em></tt> refers to a global
+variable.</p></div>
+<div class="paragraph"><p>If a procedure is active, then <tt><em>varName</em></tt> refers to a parameter
+or local variable of the procedure, unless the <tt><em>global</em></tt> command
+has been invoked to declare <tt><em>varName</em></tt> to be global.</p></div>
+<div class="paragraph"><p>The <tt>::</tt> prefix may also be used to explicitly reference a variable
+in the global scope.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_setref">setref</h3>
+<div class="paragraph"><p><tt><strong>setref</strong> <em>reference string</em></tt></p></div>
+<div class="paragraph"><p>Store a new string in <tt><em>reference</em></tt>, replacing the existing string.
+The reference must be a valid reference create with the <a href="#_ref"><strong><tt>ref</tt></strong></a>
+command.</p></div>
+<div class="paragraph"><p>See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_signal">signal</h3>
+<div class="paragraph"><p>Command for signal handling.</p></div>
+<div class="paragraph"><p>See <a href="#_kill"><strong><tt>kill</tt></strong></a> for the different forms which may be used to specify signals.</p></div>
+<div class="paragraph"><p>Commands which return a list of signal names do so using the canonical form:
+"<tt>SIGINT SIGTERM</tt>".</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>signal handle</strong> ?<em>signals ...</em>?</tt>
+</dt>
+<dd>
+<p>
+    If no signals are given, returns a list of all signals which are currently
+    being handled.
+    If signals are specified, these are added to the list of signals currently
+    being handled.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>signal ignore</strong> ?<em>signals ...</em>?</tt>
+</dt>
+<dd>
+<p>
+    If no signals are given, returns a lists all signals which are currently
+    being ignored.
+    If signals are specified, these are added to the list of signals
+    currently being ignored. These signals are still delivered, but
+    are not considered by <a href="#_catch"><strong><tt>catch</tt></strong></a> <tt>-signal</tt> or <a href="#_try"><strong><tt>try</tt></strong></a> <tt>-signal</tt>. Use
+    <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>check</tt> to determine which signals have occurred but
+    been ignored.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>signal default</strong> ?<em>signals ...</em>?</tt>
+</dt>
+<dd>
+<p>
+    If no signals are given, returns a lists all signals which are currently have
+    the default behaviour.
+    If signals are specified, these are added to the list of signals which have
+    the default behaviour.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>signal check ?-clear?</strong> ?<em>signals ...</em>?</tt>
+</dt>
+<dd>
+<p>
+    Returns a list of signals which have been delivered to the process
+    but are <em>ignored</em>. If signals are specified, only that set of signals will
+    be checked, otherwise all signals will be checked.
+    If <tt>-clear</tt> is specified, any signals returned are removed and will not be
+    returned by subsequent calls to <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>check</tt> unless delivered again.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>signal throw</strong> ?<em>signal</em>?</tt>
+</dt>
+<dd>
+<p>
+    Raises the given signal, which defaults to <tt>SIGINT</tt> if not specified.
+    The behaviour is identical to:
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>kill signal [pid]</tt></pre>
+</div></div>
+</dd>
+</dl></div>
+<div class="paragraph"><p>Note that <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>handle</tt> and <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>ignore</tt> represent two forms of signal
+handling. <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>handle</tt> is used in conjunction with <a href="#_catch"><strong><tt>catch</tt></strong></a> <tt>-signal</tt> or <a href="#_try"><strong><tt>try</tt></strong></a> <tt>-signal</tt>
+to immediately abort execution when the signal is delivered. Alternatively, <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>ignore</tt>
+is used in conjunction with <a href="#_signal"><strong><tt>signal</tt></strong></a> <tt>check</tt> to handle signal synchronously. Consider the
+two examples below.</p></div>
+<div class="paragraph"><p>Prevent a processing from taking too long</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>signal handle SIGALRM
+alarm 20
+try -signal {
+    .. possibly long running process ..
+    alarm 0
+} on signal {sig} {
+    puts stderr "Process took too long"
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>Handle SIGHUP to reconfigure:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>signal ignore SIGHUP
+while {1} {
+    ... handle configuration/reconfiguration ...
+    while {[signal check -clear SIGHUP] eq ""} {
+        ... do processing ..
+    }
+    # Received SIGHUP, so reconfigure
+}</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_sleep">sleep</h3>
+<div class="paragraph"><p><tt><strong>sleep</strong> <em>seconds</em></tt></p></div>
+<div class="paragraph"><p>Pauses for the given number of seconds, which may be a floating
+point value less than one to sleep for less than a second, or an
+integer to sleep for one or more seconds.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_source">source</h3>
+<div class="paragraph"><p><tt><strong>source</strong> <em>fileName</em></tt></p></div>
+<div class="paragraph"><p>Read file <tt><em>fileName</em></tt> and pass the contents to the Tcl interpreter
+as a sequence of commands to execute in the normal fashion.  The return
+value of <a href="#_source"><strong><tt>source</tt></strong></a> is the return value of the last command executed
+from the file.  If an error occurs in executing the contents of the
+file, then the <a href="#_source"><strong><tt>source</tt></strong></a> command will return that error.</p></div>
+<div class="paragraph"><p>If a <a href="#_return"><strong><tt>return</tt></strong></a> command is invoked from within the file, the remainder of
+the file will be skipped and the <a href="#_source"><strong><tt>source</tt></strong></a> command will return
+normally with the result from the <a href="#_return"><strong><tt>return</tt></strong></a> command.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_split">split</h3>
+<div class="paragraph"><p><tt><strong>split</strong> <em>string ?splitChars?</em></tt></p></div>
+<div class="paragraph"><p>Returns a list created by splitting <tt><em>string</em></tt> at each character
+that is in the <tt><em>splitChars</em></tt> argument.</p></div>
+<div class="paragraph"><p>Each element of the result list will consist of the
+characters from <tt><em>string</em></tt> between instances of the
+characters in <tt><em>splitChars</em></tt>.</p></div>
+<div class="paragraph"><p>Empty list elements will be generated if <tt><em>string</em></tt> contains
+adjacent characters in <tt><em>splitChars</em></tt>, or if the first or last
+character of <tt><em>string</em></tt> is in <tt><em>splitChars</em></tt>.</p></div>
+<div class="paragraph"><p>If <tt><em>splitChars</em></tt> is an empty string then each character of
+<tt><em>string</em></tt> becomes a separate element of the result list.</p></div>
+<div class="paragraph"><p><tt><em>splitChars</em></tt> defaults to the standard white-space characters.
+For example,</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>split "comp.unix.misc" .</tt></pre>
+</div></div>
+<div class="paragraph"><p>returns <tt><em>"comp unix misc"</em></tt> and</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>split "Hello world" {}</tt></pre>
+</div></div>
+<div class="paragraph"><p>returns <tt><em>"H e l l o { } w o r l d"</em></tt>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_stackdump">stackdump</h3>
+<div class="paragraph"><p><tt><strong>stackdump</strong> <em>stacktrace</em></tt></p></div>
+<div class="paragraph"><p>Creates a human readable representation of a stack trace.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_stacktrace">stacktrace</h3>
+<div class="paragraph"><p><tt><strong>stacktrace</strong></tt></p></div>
+<div class="paragraph"><p>Returns a live stack trace as a list of <tt>proc file line proc file line ...</tt>.
+Iteratively uses <a href="#_info"><strong><tt>info</tt></strong></a> <tt>frame</tt> to create the stack trace. This stack trace is in the
+same form as produced by <a href="#_catch"><strong><tt>catch</tt></strong></a> and <a href="#_info"><strong><tt>info</tt></strong></a> <tt>stacktrace</tt></p></div>
+<div class="paragraph"><p>See also <a href="#_stackdump"><strong><tt>stackdump</tt></strong></a>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_string">string</h3>
+<div class="paragraph"><p><tt><strong>string</strong> <em>option arg ?arg ...?</em></tt></p></div>
+<div class="paragraph"><p>Perform one of several string operations, depending on <tt><em>option</em></tt>.
+The legal options (which may be abbreviated) are:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>string bytelength</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the length of the string in bytes. This will return
+    the same value as <a href="#_string"><strong><tt>string</tt></strong></a> <tt>length</tt> if UTF-8 support is not enabled,
+    or if the string is composed entirely of ASCII characters.
+    See UTF-8 AND UNICODE.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string byterange</strong> <em>string first last</em></tt>
+</dt>
+<dd>
+<p>
+    Like <a href="#_string"><strong><tt>string</tt></strong></a> <tt>range</tt> except works on bytes rather than characters.
+    These commands are identical if UTF-8 support is not enabled.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string compare ?-nocase?</strong> ?<strong>-length</strong> <em>len? string1 string2</em></tt>
+</dt>
+<dd>
+<p>
+    Perform a character-by-character comparison of strings <tt><em>string1</em></tt> and
+    <tt><em>string2</em></tt> in the same way as the C <em>strcmp</em> procedure.  Return
+    -1, 0, or 1, depending on whether <tt><em>string1</em></tt> is lexicographically
+    less than, equal to, or greater than <tt><em>string2</em></tt>. If <tt>-length</tt>
+    is specified, then only the first <tt><em>len</em></tt> characters are used
+    in the comparison.  If <tt><em>len</em></tt> is negative, it is ignored.
+    Performs a case-insensitive comparison if <tt>-nocase</tt> is specified.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string equal ?-nocase?</strong> <em>?<strong>-length</strong> len?</em> <em>string1 string2</em></tt>
+</dt>
+<dd>
+<p>
+    Returns 1 if the strings are equal, or 0 otherwise. If <tt>-length</tt>
+    is specified, then only the first <tt><em>len</em></tt> characters are used
+    in the comparison.  If <tt><em>len</em></tt> is negative, it is ignored.
+    Performs a case-insensitive comparison if <tt>-nocase</tt> is specified.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string first</strong> <em>string1 string2 ?firstIndex?</em></tt>
+</dt>
+<dd>
+<p>
+    Search <tt><em>string2</em></tt> for a sequence of characters that exactly match
+    the characters in <tt><em>string1</em></tt>.  If found, return the index of the
+    first character in the first such match within <tt><em>string2</em></tt>.  If not
+    found, return -1. If <tt><em>firstIndex</em></tt> is specified, matching will start
+    from <tt><em>firstIndex</em></tt> of <tt><em>string1</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>firstIndex</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string index</strong> <em>string charIndex</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the <tt><em>charIndex</em></tt><em>th character of the <tt>'string</em></tt>
+    argument.  A <tt><em>charIndex</em></tt> of 0 corresponds to the first
+    character of the string.
+    If <tt><em>charIndex</em></tt> is less than 0 or greater than
+    or equal to the length of the string then an empty string is
+    returned.
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>charIndex</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string is</strong> <em>class</em> ?<strong>-strict</strong>? <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns 1 if <tt><em>string</em></tt> is a valid member of the specified character
+    class, otherwise returns 0. If <tt>-strict</tt> is specified, then an
+    empty string returns 0, otherwise an empty string will return 1
+    on any class. The following character classes are recognized
+    (the class name can be abbreviated):
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>alnum</tt>
+</dt>
+<dd>
+<p>
+Any alphabet or digit character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>alpha</tt>
+</dt>
+<dd>
+<p>
+Any alphabet character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>ascii</tt>
+</dt>
+<dd>
+<p>
+Any character with a value less than 128 (those that are in the 7-bit ascii range).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>control</tt>
+</dt>
+<dd>
+<p>
+Any control character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>digit</tt>
+</dt>
+<dd>
+<p>
+Any digit character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>double</tt>
+</dt>
+<dd>
+<p>
+Any of the valid forms for a double in Tcl, with optional surrounding whitespace.
+             In case of under/overflow in the value, 0 is returned.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>graph</tt>
+</dt>
+<dd>
+<p>
+Any printing character, except space.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>integer</tt>
+</dt>
+<dd>
+<p>
+Any of the valid string formats for an integer value in Tcl, with optional surrounding whitespace.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>lower</tt>
+</dt>
+<dd>
+<p>
+Any lower case alphabet character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>print</tt>
+</dt>
+<dd>
+<p>
+Any printing character, including space.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>punct</tt>
+</dt>
+<dd>
+<p>
+Any punctuation character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>space</tt>
+</dt>
+<dd>
+<p>
+Any space character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>upper</tt>
+</dt>
+<dd>
+<p>
+Any upper case alphabet character.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>xdigit</tt>
+</dt>
+<dd>
+<p>
+Any hexadecimal digit character ([0-9A-Fa-f]).
+</p>
+</dd>
+</dl></div>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    Note that string classification does <tt><em>not</em></tt> respect UTF-8. See UTF-8 AND UNICODE
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string last</strong> <em>string1 string2 ?lastIndex?</em></tt>
+</dt>
+<dd>
+<p>
+    Search <tt><em>string2</em></tt> for a sequence of characters that exactly match
+    the characters in <tt><em>string1</em></tt>.  If found, return the index of the
+    first character in the last such match within <tt><em>string2</em></tt>.  If there
+    is no match, then return -1. If <tt><em>lastIndex</em></tt> is specified, only characters
+    up to <tt><em>lastIndex</em></tt> of <tt><em>string2</em></tt> will be considered in the match.
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>lastIndex</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string length</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a decimal string giving the number of characters in <tt><em>string</em></tt>.
+    If UTF-8 support is enabled, this may be different than the number of bytes.
+    See UTF-8 AND UNICODE
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string map ?-nocase?</strong> <em>mapping string</em></tt>
+</dt>
+<dd>
+<p>
+    Replaces substrings in <tt><em>string</em></tt> based on the key-value pairs in
+    <tt><em>mapping</em></tt>, which is a list of <tt>key value key value ...</tt> as in the form
+    returned by <a href="#_array"><strong><tt>array</tt></strong></a> <tt>get</tt>. Each instance of a key in the string will be
+    replaced with its corresponding value.  If <tt>-nocase</tt> is specified, then
+    matching is done without regard to case differences. Both key and value may
+    be multiple characters.  Replacement is done in an ordered manner, so the
+    key appearing first in the list will be checked first, and so on. <tt><em>string</em></tt> is
+    only iterated over once, so earlier key replacements will have no affect for
+    later key matches. For example,
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>string map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc</tt></pre>
+</div></div>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    will return the string <tt>01321221</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    Note that if an earlier key is a prefix of a later one, it will completely mask the later
+    one.  So if the previous example is reordered like this,
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>string map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc</tt></pre>
+</div></div>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    it will return the string <tt>02c322c222c</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string match ?-nocase?</strong> <em>pattern string</em></tt>
+</dt>
+<dd>
+<p>
+    See if <tt><em>pattern</em></tt> matches <tt><em>string</em></tt>; return 1 if it does, 0
+    if it doesn&#8217;t.  Matching is done in a fashion similar to that
+    used by the C-shell.  For the two strings to match, their contents
+    must be identical except that the following special sequences
+    may appear in <tt><em>pattern</em></tt>:
+</p>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>*</tt>
+</dt>
+<dd>
+<p>
+        Matches any sequence of characters in <tt><em>string</em></tt>,
+        including a null string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>?</tt>
+</dt>
+<dd>
+<p>
+        Matches any single character in <tt><em>string</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>[<em>chars</em>]</tt>
+</dt>
+<dd>
+<p>
+        Matches any character in the set given by <tt><em>chars</em></tt>.
+        If a sequence of the form <tt><em>x-y</em></tt> appears in <tt><em>chars</em></tt>,
+        then any character between <tt><em>x</em></tt> and <tt><em>y</em></tt>, inclusive,
+        will match.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>\x</tt>
+</dt>
+<dd>
+<p>
+        Matches the single character <tt><em>x</em></tt>.  This provides a way of
+        avoiding the special interpretation of the characters <tt>\*?[]</tt>
+        in <tt><em>pattern</em></tt>.
+</p>
+</dd>
+</dl></div>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    Performs a case-insensitive comparison if <tt>-nocase</tt> is specified.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string range</strong> <em>string first last</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a range of consecutive characters from <tt><em>string</em></tt>, starting
+    with the character whose index is <tt><em>first</em></tt> and ending with the
+    character whose index is <tt><em>last</em></tt>.  An index of 0 refers to the
+    first character of the string.
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for <tt><em>first</em></tt> and <tt><em>last</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    If <tt><em>first</em></tt> is less than zero then it is treated as if it were zero, and
+    if <tt><em>last</em></tt> is greater than or equal to the length of the string then
+    it is treated as if it were <tt>end</tt>.  If <tt><em>first</em></tt> is greater than
+    <tt><em>last</em></tt> then an empty string is returned.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string repeat</strong> <em>string count</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a new string consisting of <tt><em>string</em></tt> repeated <tt><em>count</em></tt> times.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string replace</strong> <em>string first last ?newstring?</em></tt>
+</dt>
+<dd>
+<p>
+    Removes a range of consecutive characters from <tt><em>string</em></tt>, starting
+    with the character whose index is <tt><em>first</em></tt> and ending with the
+    character whose index is <tt><em>last</em></tt>.  If <tt><em>newstring</em></tt> is specified,
+    then it is placed in the removed character range. If <tt><em>first</em></tt> is
+    less than zero then it is treated as if it were zero, and if <tt><em>last</em></tt>
+    is greater than or equal to the length of the string then it is
+    treated as if it were <tt>end</tt>. If <tt><em>first</em></tt> is greater than <tt><em>last</em></tt>
+    or the length of the initial string, or <tt><em>last</em></tt> is less than 0,
+    then the initial string is returned untouched.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string reverse</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a string that is the same length as <tt><em>string</em></tt> but
+    with its characters in the reverse order.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string tolower</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a value equal to <tt><em>string</em></tt> except that all upper case
+    letters have been converted to lower case.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string totitle</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a value equal to <tt><em>string</em></tt> except that the first character
+    is converted to title case (or upper case if there is no UTF-8 titlecase variant)
+    and all remaining characters have been converted to lower case.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string toupper</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a value equal to <tt><em>string</em></tt> except that all lower case
+    letters have been converted to upper case.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string trim</strong> <em>string ?chars?</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a value equal to <tt><em>string</em></tt> except that any leading
+    or trailing characters from the set given by <tt><em>chars</em></tt> are
+    removed.
+    If <tt><em>chars</em></tt> is not specified then white space is removed
+    (spaces, tabs, newlines, and carriage returns).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string trimleft</strong> <em>string ?chars?</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a value equal to <tt><em>string</em></tt> except that any
+    leading characters from the set given by <tt><em>chars</em></tt> are
+    removed.
+    If <tt><em>chars</em></tt> is not specified then white space is removed
+    (spaces, tabs, newlines, and carriage returns).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>string trimright</strong> <em>string ?chars?</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a value equal to <tt><em>string</em></tt> except that any
+    trailing characters from the set given by <tt><em>chars</em></tt> are
+    removed.
+    If <tt><em>chars</em></tt> is not specified then white space is removed
+    (spaces, tabs, newlines, and carriage returns).
+    Null characters are always removed.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_subst">subst</h3>
+<div class="paragraph"><p><tt><strong>subst ?-nobackslashes? ?-nocommands? ?-novariables?</strong> <em>string</em></tt></p></div>
+<div class="paragraph"><p>This command performs variable substitutions, command substitutions,
+and backslash substitutions on its string argument and returns the
+fully-substituted result. The substitutions are performed in exactly
+the same way as for Tcl commands. As a result, the string argument
+is actually substituted twice, once by the Tcl parser in the usual
+fashion for Tcl commands, and again by the subst command.</p></div>
+<div class="paragraph"><p>If any of the <tt>-nobackslashes</tt>, <tt>-nocommands</tt>, or <tt>-novariables</tt> are
+specified, then the corresponding substitutions are not performed.
+For example, if <tt>-nocommands</tt> is specified, no command substitution
+is performed: open and close brackets are treated as ordinary
+characters with no special interpretation.</p></div>
+<div class="paragraph"><p><strong>Note</strong>: when it performs its substitutions, subst does not give any
+special treatment to double quotes or curly braces. For example,
+the following script returns <tt>xyz {44}</tt>, not <tt>xyz {$a}</tt>.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set a 44
+subst {xyz {$a}}</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_switch">switch</h3>
+<div class="paragraph"><p><tt><strong>switch</strong> <em>?options? string pattern body ?pattern body ...?</em></tt></p></div>
+<div class="paragraph"><p><tt><strong>switch</strong> <em>?options? string {pattern body ?pattern body ...?}</em></tt></p></div>
+<div class="paragraph"><p>The <a href="#_switch"><strong><tt>switch</tt></strong></a> command matches its string argument against each of
+the pattern arguments in order. As soon as it finds a pattern that
+matches string it evaluates the following body and returns the
+result of that evaluation. If the last pattern argument is default
+then it matches anything. If no pattern argument matches string and
+no default is given, then the <a href="#_switch"><strong><tt>switch</tt></strong></a> command returns an empty string.
+If the initial arguments to switch start with - then they are treated
+as options. The following options are currently supported:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>-exact</tt>
+</dt>
+<dd>
+<p>
+        Use exact matching when comparing string to a
+        pattern. This is the default.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>-glob</tt>
+</dt>
+<dd>
+<p>
+        When matching string to the patterns, use glob-style
+        matching (i.e. the same as implemented by the string
+        match command).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>-regexp</tt>
+</dt>
+<dd>
+<p>
+        When matching string to the patterns, use regular
+        expression matching (i.e. the same as implemented
+        by the regexp command).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>-command <em>commandname</em></tt>
+</dt>
+<dd>
+<p>
+        When matching string to the patterns, use the given command, which
+        must be a single word. The command is invoked as
+        <em>commandname pattern string</em>, or <em>commandname -nocase pattern string</em>
+        and must return 1 if matched, or 0 if not.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>--</tt>
+</dt>
+<dd>
+<p>
+        Marks the end of options. The argument following
+        this one will be treated as string even if it starts
+        with a <tt>-</tt>.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>Two syntaxes are provided for the pattern and body arguments. The
+first uses a separate argument for each of the patterns and commands;
+this form is convenient if substitutions are desired on some of the
+patterns or commands. The second form places all of the patterns
+and commands together into a single argument; the argument must
+have proper list structure, with the elements of the list being the
+patterns and commands. The second form makes it easy to construct
+multi-line <a href="#_switch"><strong><tt>switch</tt></strong></a> commands, since the braces around the whole list
+make it unnecessary to include a backslash at the end of each line.
+Since the pattern arguments are in braces in the second form, no
+command or variable substitutions are performed on them; this makes
+the behaviour of the second form different than the first form in
+some cases.</p></div>
+<div class="paragraph"><p>If a body is specified as <tt>-</tt> it means that the body for the next
+pattern should also be used as the body for this pattern (if the
+next pattern also has a body of <tt>-</tt> then the body after that is
+used, and so on). This feature makes it possible to share a single
+body among several patterns.</p></div>
+<div class="paragraph"><p>Below are some examples of <a href="#_switch"><strong><tt>switch</tt></strong></a> commands:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>switch abc a - b {format 1} abc {format 2} default {format 3}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return 2,</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>switch -regexp aaab {
+       ^a.*b$ -
+       b {format 1}
+       a* {format 2}
+       default {format 3}
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return 1, and</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>switch xyz {
+       a -
+       b {format 1}
+       a* {format 2}
+       default {format 3}
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>will return 3.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_tailcall">tailcall</h3>
+<div class="paragraph"><p><tt><strong>tailcall</strong> <em>cmd ?arg...?</em></tt></p></div>
+<div class="paragraph"><p>The <a href="#_tailcall"><strong><tt>tailcall</tt></strong></a> command provides an optimised way of invoking a command whilst replacing
+the current call frame. This is similar to <em>exec</em> in Bourne Shell.</p></div>
+<div class="paragraph"><p>The following are identical except the first immediately replaces the current call frame.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>tailcall a b c</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>return [uplevel 1 [list a b c]]</tt></pre>
+</div></div>
+<div class="paragraph"><p><a href="#_tailcall"><strong><tt>tailcall</tt></strong></a> is useful as a dispatch mechanism:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>proc a {cmd args} {
+  tailcall sub_$cmd {*}$args
+}
+proc sub_cmd1 ...
+proc sub_cmd2 ...</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_tell">tell</h3>
+<div class="paragraph"><p><tt><strong>tell</strong> <em>fileId</em></tt></p></div>
+<div class="paragraph"><p><tt><em>fileId</em> <strong>tell</strong></tt></p></div>
+<div class="paragraph"><p>Returns a decimal string giving the current access position in
+<tt><em>fileId</em></tt>.</p></div>
+<div class="paragraph"><p><tt><em>fileId</em></tt> must have been the return value from a previous call to
+<a href="#_open"><strong><tt>open</tt></strong></a>, or it may be <tt>stdin</tt>, <tt>stdout</tt>, or <tt>stderr</tt> to refer to one
+of the standard I/O channels.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_throw">throw</h3>
+<div class="paragraph"><p><tt><strong>throw</strong> <em>code ?msg?</em></tt></p></div>
+<div class="paragraph"><p>This command throws an exception (return) code along with an optional message.
+This command is mostly for convenient usage with <a href="#_try"><strong><tt>try</tt></strong></a>.</p></div>
+<div class="paragraph"><p>The command <tt>throw break</tt> is equivalent to <tt>break</tt>.
+The command <tt>throw 20 message</tt> can be caught with an <tt>on 20 ...</tt> clause to <a href="#_try"><strong><tt>try</tt></strong></a>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_time">time</h3>
+<div class="paragraph"><p><tt><strong>time</strong> <em>command ?count?</em></tt></p></div>
+<div class="paragraph"><p>This command will call the Tcl interpreter <tt><em>count</em></tt>
+times to execute <tt><em>command</em></tt> (or once if <tt><em>count</em></tt> isn&#8217;t
+specified).  It will then return a string of the form</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>503 microseconds per iteration</tt></pre>
+</div></div>
+<div class="paragraph"><p>which indicates the average amount of time required per iteration,
+in microseconds.</p></div>
+<div class="paragraph"><p>Time is measured in elapsed time, not CPU time.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_try">try</h3>
+<div class="paragraph"><p><tt><strong>try</strong> <em>?catchopts? tryscript</em> ?<strong>on</strong> <em>returncodes {?resultvar? ?optsvar?} handlerscript ...</em>? ?<strong>finally</strong> <em>finalscript</em>?</tt></p></div>
+<div class="paragraph"><p>The <a href="#_try"><strong><tt>try</tt></strong></a> command is provided as a convenience for exception handling.</p></div>
+<div class="paragraph"><p>This interpeter first evaluates <tt><em>tryscript</em></tt> under the effect of the catch
+options <tt><em>catchopts</em></tt> (e.g. <tt>-signal -noexit --</tt>, see <a href="#_catch"><strong><tt>catch</tt></strong></a>).</p></div>
+<div class="paragraph"><p>It then evaluates the script for the first matching <em>on</em> handler
+(there many be zero or more) based on the return code from the <a href="#_try"><strong><tt>try</tt></strong></a>
+section. For example a normal <tt>JIM_ERR</tt> error will be matched by
+an <em>on error</em> handler.</p></div>
+<div class="paragraph"><p>Finally, any <tt><em>finalscript</em></tt> is evaluated.</p></div>
+<div class="paragraph"><p>The result of this command is the result of <tt><em>tryscript</em></tt>, except in the
+case where an exception occurs in a matching <em>on</em> handler script or the <em>finally</em> script,
+in which case the result is this new exception.</p></div>
+<div class="paragraph"><p>The specified <tt><em>returncodes</em></tt> is a list of return codes either as names (<em>ok</em>, <em>error</em>, <em>break</em>, etc.)
+or as integers.</p></div>
+<div class="paragraph"><p>If <tt><em>resultvar</em></tt> and <tt><em>optsvar</em></tt> are specified, they are set as for <a href="#_catch"><strong><tt>catch</tt></strong></a> before evaluating
+the matching handler.</p></div>
+<div class="paragraph"><p>For example:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set f [open input]
+try -signal {
+    process $f
+} on {continue break} {} {
+    error "Unexpected break/continue"
+} on error {msg opts} {
+    puts "Dealing with error"
+    return {*}$opts $msg
+} on signal sig {
+    puts "Got signal: $sig"
+} finally {
+    $f close
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p>If break, continue or error are raised, they are dealt with by the matching
+handler.</p></div>
+<div class="paragraph"><p>In any case, the file will be closed via the <em>finally</em> clause.</p></div>
+<div class="paragraph"><p>See also <a href="#_throw"><strong><tt>throw</tt></strong></a>, <a href="#_catch"><strong><tt>catch</tt></strong></a>, <a href="#_return"><strong><tt>return</tt></strong></a>, <a href="#_error"><strong><tt>error</tt></strong></a>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_unknown">unknown</h3>
+<div class="paragraph"><p><tt><strong>unknown</strong> <em>cmdName ?arg arg &#8230;?</em></tt></p></div>
+<div class="paragraph"><p>This command doesn&#8217;t actually exist as part of Tcl, but Tcl will
+invoke it if it does exist.</p></div>
+<div class="paragraph"><p>If the Tcl interpreter encounters a command name for which there
+is not a defined command, then Tcl checks for the existence of
+a command named <a href="#_unknown"><strong><tt>unknown</tt></strong></a>.</p></div>
+<div class="paragraph"><p>If there is no such command, then the interpreter returns an
+error.</p></div>
+<div class="paragraph"><p>If the <a href="#_unknown"><strong><tt>unknown</tt></strong></a> command exists, then it is invoked with
+arguments consisting of the fully-substituted name and arguments
+for the original non-existent command.</p></div>
+<div class="paragraph"><p>The <a href="#_unknown"><strong><tt>unknown</tt></strong></a> command typically does things like searching
+through library directories for a command procedure with the name
+<tt><em>cmdName</em></tt>, or expanding abbreviated command names to full-length,
+or automatically executing unknown commands as UNIX sub-processes.</p></div>
+<div class="paragraph"><p>In some cases (such as expanding abbreviations) <a href="#_unknown"><strong><tt>unknown</tt></strong></a> will
+change the original command slightly and then (re-)execute it.
+The result of the <a href="#_unknown"><strong><tt>unknown</tt></strong></a> command is used as the result for
+the original non-existent command.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_unset">unset</h3>
+<div class="paragraph"><p><tt><strong>unset ?-nocomplain? ?--?</strong> <em>?name name &#8230;?</em></tt></p></div>
+<div class="paragraph"><p>Remove variables.
+Each <tt><em>name</em></tt> is a variable name, specified in any of the
+ways acceptable to the <a href="#_set"><strong><tt>set</tt></strong></a> command.</p></div>
+<div class="paragraph"><p>If a <tt><em>name</em></tt> refers to an element of an array, then that
+element is removed without affecting the rest of the array.</p></div>
+<div class="paragraph"><p>If a <tt><em>name</em></tt> consists of an array name with no parenthesized
+index, then the entire array is deleted.</p></div>
+<div class="paragraph"><p>The <a href="#_unset"><strong><tt>unset</tt></strong></a> command returns an empty string as result.</p></div>
+<div class="paragraph"><p>An error occurs if any of the variables doesn&#8217;t exist, unless <em>-nocomplain</em>
+is specified. The <em>--</em> argument may be specified to stop option processing
+in case the variable name may be <em>-nocomplain</em>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_upcall">upcall</h3>
+<div class="paragraph"><p><tt><strong>upcall</strong> <em>command ?args &#8230;?</em></tt></p></div>
+<div class="paragraph"><p>May be used from within a proc defined as <a href="#_local"><strong><tt>local</tt></strong></a> <a href="#_proc"><strong><tt>proc</tt></strong></a> in order to call
+the previous, hidden version of the same command.</p></div>
+<div class="paragraph"><p>If there is no previous definition of the command, an error is returned.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_uplevel">uplevel</h3>
+<div class="paragraph"><p><tt><strong>uplevel</strong> <em>?level? command ?command &#8230;?</em></tt></p></div>
+<div class="paragraph"><p>All of the <tt><em>command</em></tt> arguments are concatenated as if they had
+been passed to <a href="#_concat"><strong><tt>concat</tt></strong></a>; the result is then evaluated in the
+variable context indicated by <tt><em>level</em></tt>.  <a href="#_uplevel"><strong><tt>uplevel</tt></strong></a> returns
+the result of that evaluation.  If <tt><em>level</em></tt> is an integer, then
+it gives a distance (up the procedure calling stack) to move before
+executing the command.  If <tt><em>level</em></tt> consists of <tt>#</tt> followed by
+a number then the number gives an absolute level number.  If <tt><em>level</em></tt>
+is omitted then it defaults to <tt>1</tt>.  <tt><em>level</em></tt> cannot be
+defaulted if the first <tt><em>command</em></tt> argument starts with a digit or <tt>#</tt>.</p></div>
+<div class="paragraph"><p>For example, suppose that procedure <em>a</em> was invoked
+from top-level, and that it called <em>b</em>, and that <em>b</em> called <em>c</em>.
+Suppose that <em>c</em> invokes the <a href="#_uplevel"><strong><tt>uplevel</tt></strong></a> command.  If <tt><em>level</em></tt>
+is <tt>1</tt> or <tt>#2</tt>  or omitted, then the command will be executed
+in the variable context of <em>b</em>.  If <tt><em>level</em></tt> is <tt>2</tt> or <tt>#1</tt>
+then the command will be executed in the variable context of <em>a</em>.</p></div>
+<div class="paragraph"><p>If <tt><em>level</em></tt> is <em>3</em> or <tt>#0</tt> then the command will be executed
+at top-level (only global variables will be visible).
+The <a href="#_uplevel"><strong><tt>uplevel</tt></strong></a> command causes the invoking procedure to disappear
+from the procedure calling stack while the command is being executed.
+In the above example, suppose <em>c</em> invokes the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>uplevel 1 {set x 43; d}</tt></pre>
+</div></div>
+<div class="paragraph"><p>where <em>d</em> is another Tcl procedure.  The <a href="#_set"><strong><tt>set</tt></strong></a> command will
+modify the variable <em>x</em> in <em>b&#8217;s context, and 'd</em> will execute
+at level 3, as if called from <em>b</em>.  If it in turn executes
+the command</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>uplevel {set x 42}</tt></pre>
+</div></div>
+<div class="paragraph"><p>then the <a href="#_set"><strong><tt>set</tt></strong></a> command will modify the same variable <em>x</em> in <em>b&#8217;s
+context:  the procedure 'c</em> does not appear to be on the call stack
+when <em>d</em> is executing.  The command <a href="#_info"><strong><tt>info</tt></strong></a> <tt>level</tt> may
+be used to obtain the level of the current procedure.</p></div>
+<div class="paragraph"><p><a href="#_uplevel"><strong><tt>uplevel</tt></strong></a> makes it possible to implement new control
+constructs as Tcl procedures (for example, <a href="#_uplevel"><strong><tt>uplevel</tt></strong></a> could
+be used to implement the <a href="#_while"><strong><tt>while</tt></strong></a> construct as a Tcl procedure).</p></div>
+</div>
+<div class="sect2">
+<h3 id="_upvar">upvar</h3>
+<div class="paragraph"><p><tt><strong>upvar</strong> <em>?level? otherVar myVar ?otherVar myVar &#8230;?</em></tt></p></div>
+<div class="paragraph"><p>This command arranges for one or more local variables in the current
+procedure to refer to variables in an enclosing procedure call or
+to global variables.</p></div>
+<div class="paragraph"><p><tt><em>level</em></tt> may have any of the forms permitted for the <a href="#_uplevel"><strong><tt>uplevel</tt></strong></a>
+command, and may be omitted if the first letter of the first <tt><em>otherVar</em></tt>
+isn&#8217;t <tt>#</tt> or a digit (it defaults to <em>1</em>).</p></div>
+<div class="paragraph"><p>For each <tt><em>otherVar</em></tt> argument, <a href="#_upvar"><strong><tt>upvar</tt></strong></a> makes the variable
+by that name in the procedure frame given by <tt><em>level</em></tt> (or at
+global level, if <tt><em>level</em></tt> is <tt>#0</tt>) accessible
+in the current procedure by the name given in the corresponding
+<tt><em>myVar</em></tt> argument.</p></div>
+<div class="paragraph"><p>The variable named by <tt><em>otherVar</em></tt> need not exist at the time of the
+call;  it will be created the first time <tt><em>myVar</em></tt> is referenced, just like
+an ordinary variable.</p></div>
+<div class="paragraph"><p><a href="#_upvar"><strong><tt>upvar</tt></strong></a> may only be invoked from within procedures.</p></div>
+<div class="paragraph"><p><a href="#_upvar"><strong><tt>upvar</tt></strong></a> returns an empty string.</p></div>
+<div class="paragraph"><p>The <a href="#_upvar"><strong><tt>upvar</tt></strong></a> command simplifies the implementation of call-by-name
+procedure calling and also makes it easier to build new control constructs
+as Tcl procedures.
+For example, consider the following procedure:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>proc add2 name {
+    upvar $name x
+    set x [expr $x+2]
+}</tt></pre>
+</div></div>
+<div class="paragraph"><p><em>add2</em> is invoked with an argument giving the name of a variable,
+and it adds two to the value of that variable.
+Although <em>add2</em> could have been implemented using <a href="#_uplevel"><strong><tt>uplevel</tt></strong></a>
+instead of <a href="#_upvar"><strong><tt>upvar</tt></strong></a>, <a href="#_upvar"><strong><tt>upvar</tt></strong></a> makes it simpler for <em>add2</em>
+to access the variable in the caller&#8217;s procedure frame.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_while">while</h3>
+<div class="paragraph"><p><tt><strong>while</strong> <em>test body</em></tt></p></div>
+<div class="paragraph"><p>The <tt><em>while</em></tt> command evaluates <tt><em>test</em></tt> as an expression
+(in the same way that <a href="#_expr"><strong><tt>expr</tt></strong></a> evaluates its argument).
+The value of the expression must be numeric; if it is non-zero
+then <tt><em>body</em></tt> is executed by passing it to the Tcl interpreter.</p></div>
+<div class="paragraph"><p>Once <tt><em>body</em></tt> has been executed then <tt><em>test</em></tt> is evaluated
+again, and the process repeats until eventually <tt><em>test</em></tt>
+evaluates to a zero numeric value.  <a href="#_continue"><strong><tt>continue</tt></strong></a>
+commands may be executed inside <tt><em>body</em></tt> to terminate the current
+iteration of the loop, and <a href="#_break"><strong><tt>break</tt></strong></a>
+commands may be executed inside <tt><em>body</em></tt> to cause immediate
+termination of the <a href="#_while"><strong><tt>while</tt></strong></a> command.</p></div>
+<div class="paragraph"><p>The <a href="#_while"><strong><tt>while</tt></strong></a> command always returns an empty string.</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_optional_extensions">OPTIONAL-EXTENSIONS</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The following extensions may or may not be available depending upon
+what options were selected when Jim Tcl was built.</p></div>
+<div class="sect2">
+<h3 id="cmd_1">posix: os.fork, os.wait, os.gethostname, os.getids, os.uptime</h3>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>os.fork</strong></tt>
+</dt>
+<dd>
+<p>
+    Invokes <em>fork(2)</em> and returns the result.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>os.wait -nohang</strong> <em>pid</em></tt>
+</dt>
+<dd>
+<p>
+    Invokes waitpid(2), with WNOHANG if <tt>-nohang</tt> is specified.
+    Returns a list of 3 elements.
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>{0 none 0} if -nohang is specified, and the process is still alive.</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>{-1 error &lt;error-description&gt;} if the process does not exist or has already been waited for.</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>{&lt;pid&gt; exit &lt;exit-status&gt;} if the process exited normally.</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>{&lt;pid&gt; signal &lt;signal-number&gt;} if the process terminated on a signal.</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>{&lt;pid&gt; other 0} otherwise (core dump, stopped, continued, etc.)</tt></pre>
+</div></div>
+</dd>
+<dt class="hdlist1">
+<tt><strong>os.gethostname</strong></tt>
+</dt>
+<dd>
+<p>
+    Invokes <em>gethostname(3)</em> and returns the result.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>os.getids</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the various user/group ids for the current process.
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>jim&gt; os.getids
+uid 1000 euid 1000 gid 100 egid 100</tt></pre>
+</div></div>
+</dd>
+<dt class="hdlist1">
+<tt><strong>os.uptime</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the number of seconds since system boot. See description of <em>uptime</em> in <em>sysinfo(2)</em>.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_ansi_i_o_aio_and_eventloop_api">ANSI I/O (aio) and EVENTLOOP API</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Jim provides an alternative object-based API for I/O.</p></div>
+<div class="paragraph"><p>See <a href="#_open"><strong><tt>open</tt></strong></a> and <a href="#_socket"><strong><tt>socket</tt></strong></a> for commands which return an I/O handle.</p></div>
+<div class="sect2">
+<h3 id="_aio">aio</h3>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>$handle <strong>accept</strong></tt>
+</dt>
+<dd>
+<p>
+    Server socket only: Accept a connection and return stream
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>buffering none|line|full</strong></tt>
+</dt>
+<dd>
+<p>
+    Sets the buffering mode of the stream.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>close</strong> ?r(ead)|w(rite)?</tt>
+</dt>
+<dd>
+<p>
+    Closes the stream.
+        The  two-argument form is a "half-close" on a socket. See the <tt>shutdown(2)</tt> man page.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>copyto</strong> <em>tofd ?size?</em></tt>
+</dt>
+<dd>
+<p>
+    Copy bytes to the file descriptor <tt><em>tofd</em></tt>. If <tt><em>size</em></tt> is specified, at most
+    that many bytes will be copied. Otherwise copying continues until the end
+    of the input file. Returns the number of bytes actually copied.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>eof</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns 1 if stream is at eof
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>filename</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the original filename associated with the handle.
+    Handles returned by <a href="#_socket"><strong><tt>socket</tt></strong></a> give the socket type instead of a filename.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>flush</strong></tt>
+</dt>
+<dd>
+<p>
+    Flush the stream
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>gets</strong> <em>?var?</em></tt>
+</dt>
+<dd>
+<p>
+    Read one line and return it or store it in the var
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>isatty</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns 1 if the stream is a tty device.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>ndelay ?0|1?</strong></tt>
+</dt>
+<dd>
+<p>
+    Set O_NDELAY (if arg). Returns current/new setting.
+    Note that in general ANSI I/O interacts badly with non-blocking I/O.
+    Use with care.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>puts ?-nonewline?</strong> <em>str</em></tt>
+</dt>
+<dd>
+<p>
+    Write the string, with newline unless -nonewline
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>read ?-nonewline?</strong> <em>?len?</em></tt>
+</dt>
+<dd>
+<p>
+    Read and return bytes from the stream. To eof if no len.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>recvfrom</strong> <em>maxlen ?addrvar?</em></tt>
+</dt>
+<dd>
+<p>
+    Receives a message from the handle via recvfrom(2) and returns it.
+    At most <tt><em>maxlen</em></tt> bytes are read.
+    If <tt><em>addrvar</em></tt> is specified, the sending address of the message is stored in
+    the named variable in the form <em>addr:port</em>. See <a href="#_socket"><strong><tt>socket</tt></strong></a> for details.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>seek</strong> <em>offset</em> <strong>?start|current|end?</strong></tt>
+</dt>
+<dd>
+<p>
+    Seeks in the stream (default <em>current</em>)
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>sendto</strong> <em>str ?addr:?port</em></tt>
+</dt>
+<dd>
+<p>
+    Sends the string, <tt><em>str</em></tt>, to the given address via the socket using sendto(2).
+    This is intended for udp/dgram sockets and may give an error or behave in unintended
+    ways for other handle types.
+    Returns the number of bytes written.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>tell</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the current seek position
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_fconfigure">fconfigure</h3>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>fconfigure</strong> <em>handle</em> <strong>?-blocking 0|1? ?-buffering noneline|full? ?-translation</strong> <em>mode</em>?</tt>
+</dt>
+<dd>
+<p>
+    For compatibility with Tcl, a limited form of the <a href="#_fconfigure"><strong><tt>fconfigure</tt></strong></a>
+    command is supported.
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+<a href="#_fconfigure"><strong><tt>fconfigure</tt></strong></a> <tt>... -blocking</tt> maps to <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>ndelay</tt>
+</p>
+</li>
+<li>
+<p>
+<a href="#_fconfigure"><strong><tt>fconfigure</tt></strong></a> <tt>... -buffering</tt> maps to <a href="#_aio"><strong><tt>aio</tt></strong></a> <tt>buffering</tt>
+</p>
+</li>
+<li>
+<p>
+<a href="#_fconfigure"><strong><tt>fconfigure</tt></strong></a> <tt>... -translation</tt> is accepted but ignored
+</p>
+</li>
+</ul></div>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="cmd_2">eventloop: after, vwait, update</h3>
+<div class="paragraph"><p>The following commands allow a script to be invoked when the given condition occurs.
+If no script is given, returns the current script. If the given script is the empty, the
+handler is removed.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>$handle <strong>readable</strong> <em>?readable-script?</em></tt>
+</dt>
+<dd>
+<p>
+    Sets or returns the script for when the socket is readable.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>writable</strong> <em>?writable-script?</em></tt>
+</dt>
+<dd>
+<p>
+    Sets or returns the script for when the socket is writable.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$handle <strong>onexception</strong> <em>?exception-script?</em></tt>
+</dt>
+<dd>
+<p>
+    Sets or returns the script for when when oob data received.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>For compatibility with <em>Tcl</em>, these may be prefixed with <tt>fileevent</tt>.  e.g.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+</dt>
+<dd>
+<p>
+    <tt>fileevent $handle <strong>readable</strong> <em>...</em></tt>
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>Time-based execution is also available via the eventloop API.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>after</strong> <em>ms</em></tt>
+</dt>
+<dd>
+<p>
+    Sleeps for the given number of milliseconds. No events are
+    processed during this time.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>after</strong> <em>ms</em>|<strong>idle</strong> script ?script ...?'</tt>
+</dt>
+<dd>
+<p>
+    The scripts are concatenated and executed after the given
+    number of milliseconds have elapsed.  If <em>idle</em> is specified,
+    the script will run the next time the event loop is processed
+    with <a href="#cmd_2"><strong><tt>vwait</tt></strong></a> or <a href="#cmd_2"><strong><tt>update</tt></strong></a>. The script is only run once and
+    then removed.  Returns an event id.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>after cancel</strong> <em>id|command</em></tt>
+</dt>
+<dd>
+<p>
+    Cancels an <a href="#cmd_2"><strong><tt>after</tt></strong></a> event with the given event id or matching
+    command (script).  Returns the number of milliseconds
+    remaining until the event would have fired.  Returns the
+    empty string if no matching event is found.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>after info</strong> <em>?id?</em></tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>id</em></tt> is not given, returns a list of current <a href="#cmd_2"><strong><tt>after</tt></strong></a>
+    events.  If <tt><em>id</em></tt> is given, returns a list containing the
+    associated script and either <em>timer</em> or <em>idle</em> to indicated
+    the type of the event. An error occurs if <tt><em>id</em></tt> does not
+    match an event.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>vwait</strong> <em>variable</em></tt>
+</dt>
+<dd>
+<p>
+    A call to <a href="#cmd_2"><strong><tt>vwait</tt></strong></a> is enters the eventloop. <a href="#cmd_2"><strong><tt>vwait</tt></strong></a> processes
+    events until the named (global) variable changes or all
+    event handlers are removed. The variable need not exist
+    beforehand.  If there are no event handlers defined, <a href="#cmd_2"><strong><tt>vwait</tt></strong></a>
+    returns immediately.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>update ?idletasks?</strong></tt>
+</dt>
+<dd>
+<p>
+    A call to <a href="#cmd_2"><strong><tt>update</tt></strong></a> enters the eventloop to process expired events, but
+    no new events. If <em>idletasks</em> is specified, only expired time events are handled,
+    not file events.
+    Returns once handlers have been run for all expired events.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>Scripts are executed at the global scope. If an error occurs during a handler script,
+an attempt is made to call (the user-defined command) <tt>bgerror</tt> with the details of the error.
+If the <tt>bgerror</tt> command does not exist, the error message details are printed to stderr instead.</p></div>
+<div class="paragraph"><p>If a file event handler script generates an error, the handler is automatically removed
+to prevent infinite errors. (A time event handler is always removed after execution).</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>bgerror</strong> <em>msg</em></tt>
+</dt>
+<dd>
+<p>
+    Called when an event handler script generates an error. Note that the normal command resolution
+        rules are used for bgerror. First the name is resolved in the current namespace, then in the
+        global scope.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_socket">socket</h3>
+<div class="paragraph"><p>Various socket types may be created.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>socket unix</strong> <em>path</em></tt>
+</dt>
+<dd>
+<p>
+    A unix domain socket client.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>socket unix.server</strong> <em>path</em></tt>
+</dt>
+<dd>
+<p>
+    A unix domain socket server.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>socket ?-ipv6? stream</strong> <em>addr:port</em></tt>
+</dt>
+<dd>
+<p>
+    A TCP socket client. (See the forms for <tt><em>addr</em></tt> below)
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>socket ?-ipv6? stream.server</strong> <em>?addr:?port</em></tt>
+</dt>
+<dd>
+<p>
+    A TCP socket server (<tt><em>addr</em></tt> defaults to <tt>0.0.0.0</tt> for IPv4 or <tt>[::]</tt> for IPv6).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>socket ?-ipv6? dgram</strong> ?<em>addr:port</em>?</tt>
+</dt>
+<dd>
+<p>
+    A UDP socket client. If the address is not specified,
+    the client socket will be unbound and <em>sendto</em> must be used
+    to indicated the destination.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>socket ?-ipv6? dgram.server</strong> <em>addr:port</em></tt>
+</dt>
+<dd>
+<p>
+    A UDP socket server.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>socket pipe</strong></tt>
+</dt>
+<dd>
+<p>
+    A pipe. Note that unlike all other socket types, this command returns
+    a list of two channels: {read write}
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>socket pair</strong></tt>
+</dt>
+<dd>
+<p>
+    A socketpair (see socketpair(2)). Like <a href="#_socket"><strong><tt>socket</tt></strong></a> <tt>pipe</tt>, this command returns
+    a list of two channels: {s1 s2}. These channels are both readable and writable.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>This command creates a socket connected (client) or bound (server) to the given
+address.</p></div>
+<div class="paragraph"><p>The returned value is channel and may generally be used with the various file I/O
+commands (gets, puts, read, etc.), either as object-based syntax or Tcl-compatible syntax.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set f [socket stream www.google.com:80]
+aio.sockstream1
+$f puts -nonewline "GET / HTTP/1.0\r\n\r\n"
+$f gets
+HTTP/1.0 302 Found
+$f close</tt></pre>
+</div></div>
+<div class="paragraph"><p>Server sockets, however support only <em>accept</em>, which is most useful in conjunction with
+the EVENTLOOP API.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>set f [socket stream.server 80]
+$f readable {
+    set client [$f accept]
+    $client gets $buf
+    ...
+    $client puts -nonewline "HTTP/1.1 404 Not found\r\n"
+    $client close
+}
+vwait done</tt></pre>
+</div></div>
+<div class="paragraph"><p>The address, <tt><em>addr</em></tt>, can be given in one of the following forms:</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+For IPv4 socket types, an IPv4 address such as 192.168.1.1
+</p>
+</li>
+<li>
+<p>
+For IPv6 socket types, an IPv6 address such as [fe80::1234] or [::]
+</p>
+</li>
+<li>
+<p>
+A hostname
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>Note that on many systems, listening on an IPv6 address such as [::] will
+also accept requests via IPv4.</p></div>
+<div class="paragraph"><p>Where a hostname is specified, the <tt><em>first</em></tt> returned address is used
+which matches the socket type is used.</p></div>
+<div class="paragraph"><p>The special type <em>pipe</em> isn&#8217;t really a socket.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>lassign [socket pipe] r w</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt># Must close $w after exec
+exec ps &gt;@$w &amp;
+$w close</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>$r readable ...</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_syslog">syslog</h3>
+<div class="paragraph"><p><tt><strong>syslog</strong> <em>?options? ?priority? message</em></tt></p></div>
+<div class="paragraph"><p>This  command sends message to system syslog facility with given
+priority. Valid priorities are:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>emerg, alert, crit, err, error, warning, notice, info, debug</tt></pre>
+</div></div>
+<div class="paragraph"><p>If a message is specified, but no priority is specified, then a
+priority of info is used.</p></div>
+<div class="paragraph"><p>By default, facility user is used and the value of global tcl variable
+argv0 is used as ident string. However, any of the following options
+may be specified before priority to control these parameters:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>-facility</strong> <em>value</em></tt>
+</dt>
+<dd>
+<p>
+    Use specified facility instead of user. The following
+    values for facility are recognized:
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>authpriv, cron, daemon, kernel, lpr, mail, news, syslog, user,
+uucp, local0-local7</tt></pre>
+</div></div>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-ident</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Use given string instead of argv0 variable for ident string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>-options</strong> <em>integer</em></tt>
+</dt>
+<dd>
+<p>
+    Set syslog options such as <tt>LOG_CONS</tt>, <tt>LOG_NDELAY</tt>. You should
+    use numeric values of those from your system syslog.h file,
+    because I haven&#8217;t got time to implement yet another hash
+    table.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="cmd_3">pack: pack, unpack</h3>
+<div class="paragraph"><p>The optional <em>pack</em> extension provides commands to encode and decode binary strings.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>pack</strong> <em>varName value</em> <strong>-intle|-intbe|-floatle|-floatbe|-str</strong> <em>bitwidth ?bitoffset?</em></tt>
+</dt>
+<dd>
+<p>
+    Packs the binary representation of <tt><em>value</em></tt> into the variable
+    <tt><em>varName</em></tt>. The value is packed according to the given type
+    (integer/floating point/string, big-endian/little-endian), width and bit offset.
+    The variable is created if necessary (like <a href="#_append"><strong><tt>append</tt></strong></a>).
+    Ihe variable is expanded if necessary.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>unpack</strong> <em>binvalue</em> <strong>-intbe|-intle|-uintbe|-uintle|-floatbe|-floatle|-str</strong> <em>bitpos bitwidth</em></tt>
+</dt>
+<dd>
+<p>
+    Unpacks bits from <tt><em>binvalue</em></tt> at bit position <tt><em>bitpos</em></tt> and with <tt><em>bitwidth</em></tt>.
+    Interprets the value according to the type (integer/floating point/string, big-endian/little-endian
+    and signed/unsigned) and returns it. For integer types, <tt><em>bitwidth</em></tt>
+    may be up to the size of a Jim Tcl integer (typically 64 bits). For floating point types,
+    <tt><em>bitwidth</em></tt> may be 32 bits (for single precision numbers) or 64 bits (for double precision).
+    For the string type, both the width and the offset must be on a byte boundary (multiple of 8). Attempting to
+    access outside the length of the value will return 0 for integer types, 0.0 for floating point types
+    or the empty string for the string type.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_binary">binary</h3>
+<div class="paragraph"><p>The optional, pure-Tcl <em>binary</em> extension provides the Tcl-compatible <a href="#_binary"><strong><tt>binary</tt></strong></a> <tt>scan</tt> and <a href="#_binary"><strong><tt>binary</tt></strong></a> <tt>format</tt>
+commands based on the low-level <a href="#cmd_3"><strong><tt>pack</tt></strong></a> and <a href="#cmd_3"><strong><tt>unpack</tt></strong></a> commands.</p></div>
+<div class="paragraph"><p>See the Tcl documentation at: <a href="http://www.tcl.tk/man/tcl8.5/TclCmd/binary.htm">http://www.tcl.tk/man/tcl8.5/TclCmd/binary.htm</a></p></div>
+<div class="paragraph"><p>Note that <em>binary format</em> with f/r/R specifiers (single-precision float) uses the value of Infinity
+ in case of overflow.</p></div>
+</div>
+<div class="sect2">
+<h3 id="cmd_4">oo: class, super</h3>
+<div class="paragraph"><p>The optional, pure-Tcl <em>oo</em> extension provides object-oriented (OO) support for Jim Tcl.</p></div>
+<div class="paragraph"><p>See the online documentation (<a href="http://jim.tcl.tk/index.html/doc/www/www/documentation/oo/">http://jim.tcl.tk/index.html/doc/www/www/documentation/oo/</a>) for more details.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>class</strong> <em>classname ?baseclasses? classvars</em></tt>
+</dt>
+<dd>
+<p>
+    Create a new class, <tt><em>classname</em></tt>, with the given dictionary
+    (<tt><em>classvars</em></tt>) as class variables. These are the initial variables
+    which all newly created objects of this class are initialised with.
+    If a list of baseclasses is given, methods and instance variables
+    are inherited.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>super</strong> <em>method ?args ...?</em></tt>
+</dt>
+<dd>
+<p>
+    From within a method, invokes the given method on the base class.
+    Note that this will only call the last baseclass given.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_tree">tree</h3>
+<div class="paragraph"><p>The optional, pure-Tcl <em>tree</em> extension implements an OO, general purpose tree structure
+similar to that provided by tcllib ::struct::tree (<a href="http://tcllib.sourceforge.net/doc/struct_tree.html">http://tcllib.sourceforge.net/doc/struct_tree.html</a>)</p></div>
+<div class="paragraph"><p>A tree is a collection of nodes, where each node (except the root node) has a single parent
+and zero or more child nodes (ordered), as well as zero or more attribute/value pairs.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>tree</strong></tt>
+</dt>
+<dd>
+<p>
+    Creates and returns a new tree object with a single node named "root".
+    All operations on the tree are invoked through this object.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>destroy</strong></tt>
+</dt>
+<dd>
+<p>
+    Destroy the tree and all it&#8217;s nodes. (Note that the the tree will also
+    be automatically garbage collected once it goes out of scope).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>set</strong> <em>nodename key value</em></tt>
+</dt>
+<dd>
+<p>
+    Set the value for the given attribute key.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>lappend</strong> <em>nodename key value ...</em></tt>
+</dt>
+<dd>
+<p>
+    Append to the (list) value(s) for the given attribute key, or set if not yet set.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>keyexists</strong> <em>nodename key</em></tt>
+</dt>
+<dd>
+<p>
+    Returns 1 if the given attribute key exists.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>get</strong> <em>nodename key</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the value associated with the given attribute key.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>getall</strong> <em>nodename</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the entire attribute dictionary associated with the given key.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>depth</strong> <em>nodename</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the depth of the given node. The depth of "root" is 0.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>parent</strong> <em>nodename</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the node name of the parent node, or "" for the root node.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>numchildren</strong> <em>nodename</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the number of child nodes.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>children</strong> <em>nodename</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a list of the child nodes.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>next</strong> <em>nodename</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the next sibling node, or "" if none.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>insert</strong> <em>nodename ?index?</em></tt>
+</dt>
+<dd>
+<p>
+    Add a new child node to the given node. The index is a list index
+    such as <tt>3</tt> or <tt>end-2</tt>. The default index is <tt>end</tt>.
+    Returns the name of the newly added node.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>walk</strong> <em>nodename</em> <strong>dfs|bfs</strong> {<em>actionvar nodevar</em>} <em>script</em></tt>
+</dt>
+<dd>
+<p>
+    Walks the tree starting from the given node, either breadth first (<tt>bfs</tt>)
+    depth first (<tt>dfs</tt>).
+    The value <tt>"enter"</tt> or <tt>"exit"</tt> is stored in variable <tt><em>actionvar</em></tt>.
+    The name of each node is stored in <tt><em>nodevar</em></tt>.
+    The script is evaluated twice for each node, on entry and exit.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>$tree <strong>dump</strong></tt>
+</dt>
+<dd>
+<p>
+    Dumps the tree contents to stdout
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_tcl_prefix">tcl::prefix</h3>
+<div class="paragraph"><p>The optional tclprefix extension provides the Tcl8.6-compatible <em>tcl::prefix</em> command
+(<a href="http://www.tcl.tk/man/tcl8.6/TclCmd/prefix.htm">http://www.tcl.tk/man/tcl8.6/TclCmd/prefix.htm</a>) for matching strings against a table
+of possible values (typically commands or options).</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>tcl::prefix all</strong> <em>table string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns a list of all elements in <tt><em>table</em></tt> that begin with the prefix <tt><em>string</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>tcl::prefix longest</strong> <em>table string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the longest common prefix of all elements in <tt><em>table</em></tt> that begin with the prefix <tt><em>string</em></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>tcl::prefix match</strong> <em>?options? table string</em></tt>
+</dt>
+<dd>
+<p>
+    If <tt><em>string</em></tt> equals one element in <tt><em>table</em></tt> or is a prefix to
+    exactly one element, the matched element is returned. If not, the
+    result depends on the <tt>-error</tt> option.
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+<tt><strong>-exact</strong></tt> Accept only exact matches.
+</p>
+</li>
+<li>
+<p>
+<tt><strong>-message</strong> <em>string</em></tt> Use <tt><em>string</em></tt> in the error message at a mismatch. Default is "option".
+</p>
+</li>
+<li>
+<p>
+<tt><strong>-error</strong> <em>options</em></tt> The options are used when no match is found. If <tt><em>options</em></tt> is
+      empty, no error is generated and an empty string is returned.
+      Otherwise the options are used as return options when
+      generating the error message. The default corresponds to
+      setting <tt>-level 0</tt>.
+</p>
+</li>
+</ul></div>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_history">history</h3>
+<div class="paragraph"><p>The optional history extension provides script access to the command line editing
+and history support available in <em>jimsh</em>. See <em>examples/jtclsh.tcl</em> for an example.
+Note: if line editing support is not available, <a href="#_history"><strong><tt>history</tt></strong></a> <tt>getline</tt> acts like <a href="#_gets"><strong><tt>gets</tt></strong></a> and
+the remaining subcommands do nothing.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>history load</strong> <em>filename</em></tt>
+</dt>
+<dd>
+<p>
+    Load history from a (text) file. If the file does not exist or is not readable,
+    it is ignored.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>history getline</strong> <em>prompt ?varname?</em></tt>
+</dt>
+<dd>
+<p>
+    Displays the given prompt and allows a line to be entered. Similarly to <a href="#_gets"><strong><tt>gets</tt></strong></a>,
+    if <tt><em>varname</em></tt> is given, it receives the line and the length of the line is returned,
+    or -1 on EOF. If <tt><em>varname</em></tt> is not given, the line is returned directly.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>history add</strong> <em>line</em></tt>
+</dt>
+<dd>
+<p>
+    Adds the given line to the history buffer.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>history save</strong> <em>filename</em></tt>
+</dt>
+<dd>
+<p>
+    Saves the current history buffer to the given file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>history show</strong></tt>
+</dt>
+<dd>
+<p>
+    Displays the current history buffer to standard output.
+</p>
+</dd>
+</dl></div>
+</div>
+<div class="sect2">
+<h3 id="_namespace">namespace</h3>
+<div class="paragraph"><p>Provides namespace-related functions. See also: <a href="http://www.tcl.tk/man/tcl8.6/TclCmd/namespace.htm">http://www.tcl.tk/man/tcl8.6/TclCmd/namespace.htm</a></p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>namespace code</strong> <em>script</em></tt>
+</dt>
+<dd>
+<p>
+    Captures the current namespace context for later execution of
+    the script <tt><em>script</em></tt>. It returns a new script in which script has
+    been wrapped in a <tt><strong>namespace inscope</strong></tt> command.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace current</strong></tt>
+</dt>
+<dd>
+<p>
+    Returns the fully-qualified name for the current namespace.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace delete</strong> <em>?namespace &#8230;?</em></tt>
+</dt>
+<dd>
+<p>
+    Deletes all commands and variables with the given namespace prefixes.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace eval</strong> <em>namespace arg ?arg&#8230;?</em></tt>
+</dt>
+<dd>
+<p>
+    Activates a namespace called <tt><em>namespace</em></tt> and evaluates some code in that context.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace origin</strong> <em>command</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the fully-qualified name of the original command to which the imported command <tt><em>command</em></tt> refers.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace parent</strong> ?namespace?</tt>
+</dt>
+<dd>
+<p>
+    Returns the fully-qualified name of the parent namespace for namespace <tt><em>namespace</em></tt>, if given, otherwise
+    for the current namespace.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace qualifiers</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns any leading namespace qualifiers for <tt><em>string</em></tt>
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace tail</strong> <em>string</em></tt>
+</dt>
+<dd>
+<p>
+    Returns the simple name at the end of a qualified string.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace upvar</strong> <em>namespace ?arg&#8230;?</em></tt>
+</dt>
+<dd>
+<p>
+    This command arranges for zero or more local variables in the current procedure to refer to variables in <tt><em>namespace</em></tt>
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>namespace which</strong> <em>?-command|-variable? name</em></tt>
+</dt>
+<dd>
+<p>
+    Looks up <tt><em>name</em></tt> as either a command (the default) or variable and returns its fully-qualified name.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="BuiltinVariables">BUILT-IN VARIABLES</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The following global variables are created automatically
+by the Tcl library.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>env</strong></tt>
+</dt>
+<dd>
+<p>
+    This variable is set by Jim as an array
+    whose elements are the environment variables for the process.
+    Reading an element will return the value of the corresponding
+    environment variable.
+    This array is initialised at startup from the <a href="#_env"><strong><tt>env</tt></strong></a> command.
+    It may be modified and will affect the environment passed to
+    commands invoked with <a href="#_exec"><strong><tt>exec</tt></strong></a>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>platform_tcl</strong></tt>
+</dt>
+<dd>
+<p>
+    This variable is set by Jim as an array containing information
+    about the platform on which Jim was built. Currently this includes
+    <em>os</em> and <em>platform</em>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>auto_path</strong></tt>
+</dt>
+<dd>
+<p>
+    This variable contains a list of paths to search for packages.
+    It defaults to a location based on where jim is installed
+    (e.g. <tt>/usr/local/lib/jim</tt>), but may be changed by <tt>jimsh</tt>
+    or the embedding application. Note that <tt>jimsh</tt> will consider
+    the environment variable <tt>$JIMLIB</tt> to be a list of colon-separated
+    list of paths to add to <tt><strong>auto_path</strong></tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>errorCode</strong></tt>
+</dt>
+<dd>
+<p>
+    This variable holds the value of the -errorcode return
+    option set by the most recent error that occurred in this
+    interpreter. This list value represents additional information
+    about the error in a form that is easy to process with
+    programs. The first element of the list identifies a general
+    class of errors, and determines the format of the rest of
+    the list. The following formats for -errorcode return options
+    are used by the Tcl core; individual applications may define
+    additional formats. Currently only <a href="#_exec"><strong><tt>exec</tt></strong></a> sets this variable.
+    Otherwise it will be <tt>NONE</tt>.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>The following global variables are set by jimsh.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt><strong>tcl_interactive</strong></tt>
+</dt>
+<dd>
+<p>
+    This variable is set to 1 if jimsh is started in interactive mode
+    or 0 otherwise.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>tcl_platform</strong></tt>
+</dt>
+<dd>
+<p>
+    This variable is set by Jim as an array containing information
+    about the platform upon which Jim was built. The following is an
+    example of the contents of this array.
+</p>
+<div class="literalblock">
+<div class="content">
+<pre><tt>tcl_platform(byteOrder)     = littleEndian
+tcl_platform(os)            = Darwin
+tcl_platform(platform)      = unix
+tcl_platform(pointerSize)   = 8
+tcl_platform(threaded)      = 0
+tcl_platform(wordSize)      = 8
+tcl_platform(pathSeparator) = :</tt></pre>
+</div></div>
+</dd>
+<dt class="hdlist1">
+<tt><strong>argv0</strong></tt>
+</dt>
+<dd>
+<p>
+    If jimsh is invoked to run a script, this variable contains the name
+    of the script.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>argv</strong></tt>
+</dt>
+<dd>
+<p>
+    If jimsh is invoked to run a script, this variable contains a list
+    of any arguments supplied to the script.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>argc</strong></tt>
+</dt>
+<dd>
+<p>
+    If jimsh is invoked to run a script, this variable contains the number
+    of arguments supplied to the script.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt><strong>jim_argv0</strong></tt>
+</dt>
+<dd>
+<p>
+    The value of argv[0] when jimsh was invoked.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_changes_in_previous_releases">CHANGES IN PREVIOUS RELEASES</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_in_v0_70">In v0.70</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+<tt>platform_tcl()</tt> settings are now automatically determined
+</p>
+</li>
+<li>
+<p>
+Add aio <tt>$handle filename</tt>
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_info"><strong><tt>info</tt></strong></a> <tt>channels</tt>
+</p>
+</li>
+<li>
+<p>
+The <em>bio</em> extension is gone. Now <a href="#_aio"><strong><tt>aio</tt></strong></a> supports <em>copyto</em>.
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_exists"><strong><tt>exists</tt></strong></a> command
+</p>
+</li>
+<li>
+<p>
+Add the pure-Tcl <em>oo</em> extension
+</p>
+</li>
+<li>
+<p>
+The <a href="#_exec"><strong><tt>exec</tt></strong></a> command now only uses vfork(), not fork()
+</p>
+</li>
+<li>
+<p>
+Unit test framework is less verbose and more Tcl-compatible
+</p>
+</li>
+<li>
+<p>
+Optional UTF-8 support
+</p>
+</li>
+<li>
+<p>
+Optional built-in regexp engine for better Tcl compatibility and UTF-8 support
+</p>
+</li>
+<li>
+<p>
+Command line editing in interactive mode, e.g. <em>jimsh</em>
+</p>
+</li>
+</ol></div>
+</div>
+<div class="sect2">
+<h3 id="_in_v0_63">In v0.63</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+<a href="#_source"><strong><tt>source</tt></strong></a> now checks that a script is complete (.i.e. not missing a brace)
+</p>
+</li>
+<li>
+<p>
+<em>info complete</em> now uses the real parser and so is 100% accurate
+</p>
+</li>
+<li>
+<p>
+Better access to live stack frames with <em>info frame</em>, <a href="#_stacktrace"><strong><tt>stacktrace</tt></strong></a> and <a href="#_stackdump"><strong><tt>stackdump</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+<a href="#_tailcall"><strong><tt>tailcall</tt></strong></a> no longer loses stack trace information
+</p>
+</li>
+<li>
+<p>
+Add <a href="#_alias"><strong><tt>alias</tt></strong></a> and <a href="#_curry"><strong><tt>curry</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+<a href="#_lambda"><strong><tt>lambda</tt></strong></a>, <a href="#_alias"><strong><tt>alias</tt></strong></a> and <a href="#_curry"><strong><tt>curry</tt></strong></a> are implemented via <a href="#_tailcall"><strong><tt>tailcall</tt></strong></a> for efficiency
+</p>
+</li>
+<li>
+<p>
+<a href="#_local"><strong><tt>local</tt></strong></a> allows procedures to be deleted automatically at the end of the current procedure
+</p>
+</li>
+<li>
+<p>
+udp sockets are now supported for both clients and servers.
+</p>
+</li>
+<li>
+<p>
+vfork-based exec is now working correctly
+</p>
+</li>
+<li>
+<p>
+Add <em>file tempfile</em>
+</p>
+</li>
+<li>
+<p>
+Add <em>socket pipe</em>
+</p>
+</li>
+<li>
+<p>
+Enhance <em>try &#8230; on &#8230; finally</em> to be more Tcl 8.6 compatible
+</p>
+</li>
+<li>
+<p>
+It is now possible to <a href="#_return"><strong><tt>return</tt></strong></a> from within <a href="#_try"><strong><tt>try</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+IPv6 support is now included
+</p>
+</li>
+<li>
+<p>
+Add <em>string is</em>
+</p>
+</li>
+<li>
+<p>
+Event handlers works better if an error occurs. eof handler has been removed.
+</p>
+</li>
+<li>
+<p>
+<a href="#_exec"><strong><tt>exec</tt></strong></a> now sets $::errorCode, and catch sets opts(-errorcode) for exit status
+</p>
+</li>
+<li>
+<p>
+Command pipelines via open "|&#8230;" are now supported
+</p>
+</li>
+<li>
+<p>
+<a href="#_pid"><strong><tt>pid</tt></strong></a> can now return pids of a command pipeline
+</p>
+</li>
+<li>
+<p>
+Add <em>info references</em>
+</p>
+</li>
+<li>
+<p>
+Add support for <em>after <tt>'ms</em></tt><em>, 'after idle</em>, <em>after info</em>, <a href="#cmd_2"><strong><tt>update</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+<a href="#_exec"><strong><tt>exec</tt></strong></a> now sets environment based on $::env
+</p>
+</li>
+<li>
+<p>
+Add <em>dict keys</em>
+</p>
+</li>
+<li>
+<p>
+Add support for <em>lsort -index</em>
+</p>
+</li>
+</ol></div>
+</div>
+<div class="sect2">
+<h3 id="_in_v0_62">In v0.62</h3>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Add support to <a href="#_exec"><strong><tt>exec</tt></strong></a> for <em>&gt;&amp;</em>, <em>&gt;&gt;&amp;</em>, <em>|&amp;</em>, <em>2&gt;@1</em>
+</p>
+</li>
+<li>
+<p>
+Fix <a href="#_exec"><strong><tt>exec</tt></strong></a> error messages when special token (e.g. <em>&gt;</em>) is the last token
+</p>
+</li>
+<li>
+<p>
+Fix <a href="#_subst"><strong><tt>subst</tt></strong></a> handling of backslash escapes.
+</p>
+</li>
+<li>
+<p>
+Allow abbreviated options for <a href="#_subst"><strong><tt>subst</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+Add support for <a href="#_return"><strong><tt>return</tt></strong></a>, <a href="#_break"><strong><tt>break</tt></strong></a>, <a href="#_continue"><strong><tt>continue</tt></strong></a> in subst
+</p>
+</li>
+<li>
+<p>
+Many <a href="#_expr"><strong><tt>expr</tt></strong></a> bug fixes
+</p>
+</li>
+<li>
+<p>
+Add support for functions in <a href="#_expr"><strong><tt>expr</tt></strong></a> (e.g. int(), abs()), and also <em>in</em>, <em>ni</em> list operations
+</p>
+</li>
+<li>
+<p>
+The variable name argument to <a href="#_regsub"><strong><tt>regsub</tt></strong></a> is now optional
+</p>
+</li>
+<li>
+<p>
+Add support for <em>unset -nocomplain</em>
+</p>
+</li>
+<li>
+<p>
+Add support for list commands: <a href="#_lassign"><strong><tt>lassign</tt></strong></a>, <a href="#_lrepeat"><strong><tt>lrepeat</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+Fully-functional <a href="#_lsearch"><strong><tt>lsearch</tt></strong></a> is now implemented
+</p>
+</li>
+<li>
+<p>
+Add <em>info nameofexecutable</em> and <em>info returncodes</em>
+</p>
+</li>
+<li>
+<p>
+Allow <a href="#_catch"><strong><tt>catch</tt></strong></a> to determine what return codes are caught
+</p>
+</li>
+<li>
+<p>
+Allow <a href="#_incr"><strong><tt>incr</tt></strong></a> to increment an unset variable by first setting to 0
+</p>
+</li>
+<li>
+<p>
+Allow <em>args</em> and optional arguments to the left or required arguments in <a href="#_proc"><strong><tt>proc</tt></strong></a>
+</p>
+</li>
+<li>
+<p>
+Add <em>file copy</em>
+</p>
+</li>
+<li>
+<p>
+Add <em>try &#8230; finally</em> command
+</p>
+</li>
+</ol></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_licence">LICENCE</h2>
+<div class="sectionbody">
+<div class="literalblock">
+<div class="content">
+<pre><tt>Copyright 2005 Salvatore Sanfilippo &lt;antirez@invece.org&gt;
+Copyright 2005 Clemens Hintze &lt;c.hintze@gmx.net&gt;
+Copyright 2005 patthoyts - Pat Thoyts &lt;patthoyts@users.sf.net&gt;
+Copyright 2008 oharboe - Oyvind Harboe - oyvind.harboe@zylin.com
+Copyright 2008 Andrew Lunn &lt;andrew@lunn.ch&gt;
+Copyright 2008 Duane Ellis &lt;openocd@duaneellis.com&gt;
+Copyright 2008 Uwe Klein &lt;uklein@klein-messgeraete.de&gt;
+Copyright 2009 Steve Bennett &lt;steveb@workware.net.au&gt;</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above
+   copyright notice, this list of conditions and the following
+   disclaimer in the documentation and/or other materials
+   provided with the distribution.</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</tt></pre>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>The views and conclusions contained in the software and documentation
+are those of the authors and should not be interpreted as representing
+official policies, either expressed or implied, of the Jim Tcl Project.</tt></pre>
+</div></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2014-05-12 11:24:57 EST
+</div>
+</div>
+</body>
+</html>
diff --git a/jim/UnicodeData.txt b/jim/UnicodeData.txt
new file mode 100755 (executable)
index 0000000..6b01d90
--- /dev/null
@@ -0,0 +1,21829 @@
+0000;<control>;Cc;0;BN;;;;;N;NULL;;;;
+0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;;
+0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;;
+0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;;
+0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;;
+0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;;
+0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;;
+0007;<control>;Cc;0;BN;;;;;N;BELL;;;;
+0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;;
+0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
+000A;<control>;Cc;0;B;;;;;N;LINE FEED (LF);;;;
+000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
+000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
+000D;<control>;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;;
+000E;<control>;Cc;0;BN;;;;;N;SHIFT OUT;;;;
+000F;<control>;Cc;0;BN;;;;;N;SHIFT IN;;;;
+0010;<control>;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;;
+0011;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;;
+0012;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;;
+0013;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;;
+0014;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;;
+0015;<control>;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;;
+0016;<control>;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;;
+0017;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;;
+0018;<control>;Cc;0;BN;;;;;N;CANCEL;;;;
+0019;<control>;Cc;0;BN;;;;;N;END OF MEDIUM;;;;
+001A;<control>;Cc;0;BN;;;;;N;SUBSTITUTE;;;;
+001B;<control>;Cc;0;BN;;;;;N;ESCAPE;;;;
+001C;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;;
+001D;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;;
+001E;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;;
+001F;<control>;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;;
+0020;SPACE;Zs;0;WS;;;;;N;;;;;
+0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
+0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;;
+0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;;
+0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;;
+0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;;
+0026;AMPERSAND;Po;0;ON;;;;;N;;;;;
+0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;;
+0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;;
+0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;;
+002A;ASTERISK;Po;0;ON;;;;;N;;;;;
+002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;;
+002C;COMMA;Po;0;CS;;;;;N;;;;;
+002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;;
+002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;;
+002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;;
+0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;;
+0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;;
+0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;;
+0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;;
+0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;;
+0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;;
+0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;;
+0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;;
+0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;;
+0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;;
+003A;COLON;Po;0;CS;;;;;N;;;;;
+003B;SEMICOLON;Po;0;ON;;;;;N;;;;;
+003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;;
+003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;;
+003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;;
+003F;QUESTION MARK;Po;0;ON;;;;;N;;;;;
+0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;;
+0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061;
+0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062;
+0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063;
+0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064;
+0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065;
+0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066;
+0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067;
+0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068;
+0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069;
+004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A;
+004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B;
+004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C;
+004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D;
+004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E;
+004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F;
+0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070;
+0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071;
+0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072;
+0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073;
+0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074;
+0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075;
+0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076;
+0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077;
+0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078;
+0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079;
+005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A;
+005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;;
+005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;;
+005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;;
+005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;;
+005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;;
+0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;;
+0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041
+0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042
+0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043
+0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044
+0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045
+0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046
+0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047
+0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048
+0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049
+006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A
+006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B
+006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C
+006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D
+006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E
+006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F
+0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050
+0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051
+0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052
+0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053
+0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054
+0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055
+0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056
+0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057
+0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058
+0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059
+007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A
+007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;;
+007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;;
+007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;;
+007E;TILDE;Sm;0;ON;;;;;N;;;;;
+007F;<control>;Cc;0;BN;;;;;N;DELETE;;;;
+0080;<control>;Cc;0;BN;;;;;N;;;;;
+0081;<control>;Cc;0;BN;;;;;N;;;;;
+0082;<control>;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;;
+0083;<control>;Cc;0;BN;;;;;N;NO BREAK HERE;;;;
+0084;<control>;Cc;0;BN;;;;;N;;;;;
+0085;<control>;Cc;0;B;;;;;N;NEXT LINE (NEL);;;;
+0086;<control>;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;;
+0087;<control>;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;;
+0088;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;;
+0089;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;;
+008A;<control>;Cc;0;BN;;;;;N;LINE TABULATION SET;;;;
+008B;<control>;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;;
+008C;<control>;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;;
+008D;<control>;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;;
+008E;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;;
+008F;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;;
+0090;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;;
+0091;<control>;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;;
+0092;<control>;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;;
+0093;<control>;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;;
+0094;<control>;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;;
+0095;<control>;Cc;0;BN;;;;;N;MESSAGE WAITING;;;;
+0096;<control>;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;;
+0097;<control>;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;;
+0098;<control>;Cc;0;BN;;;;;N;START OF STRING;;;;
+0099;<control>;Cc;0;BN;;;;;N;;;;;
+009A;<control>;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;;
+009B;<control>;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;;
+009C;<control>;Cc;0;BN;;;;;N;STRING TERMINATOR;;;;
+009D;<control>;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;;
+009E;<control>;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;;
+009F;<control>;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;;
+00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
+00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
+00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;;
+00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;;
+00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;;
+00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;;
+00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;;
+00A7;SECTION SIGN;So;0;ON;;;;;N;;;;;
+00A8;DIAERESIS;Sk;0;ON;<compat> 0020 0308;;;;N;SPACING DIAERESIS;;;;
+00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;;
+00AA;FEMININE ORDINAL INDICATOR;Ll;0;L;<super> 0061;;;;N;;;;;
+00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;;
+00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;;
+00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;;
+00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;;
+00AF;MACRON;Sk;0;ON;<compat> 0020 0304;;;;N;SPACING MACRON;;;;
+00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;;
+00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;;
+00B2;SUPERSCRIPT TWO;No;0;EN;<super> 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;;
+00B3;SUPERSCRIPT THREE;No;0;EN;<super> 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;;
+00B4;ACUTE ACCENT;Sk;0;ON;<compat> 0020 0301;;;;N;SPACING ACUTE;;;;
+00B5;MICRO SIGN;Ll;0;L;<compat> 03BC;;;;N;;;039C;;039C
+00B6;PILCROW SIGN;So;0;ON;;;;;N;PARAGRAPH SIGN;;;;
+00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;;
+00B8;CEDILLA;Sk;0;ON;<compat> 0020 0327;;;;N;SPACING CEDILLA;;;;
+00B9;SUPERSCRIPT ONE;No;0;EN;<super> 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;;
+00BA;MASCULINE ORDINAL INDICATOR;Ll;0;L;<super> 006F;;;;N;;;;;
+00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;;
+00BC;VULGAR FRACTION ONE QUARTER;No;0;ON;<fraction> 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;;
+00BD;VULGAR FRACTION ONE HALF;No;0;ON;<fraction> 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;;
+00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON;<fraction> 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;;
+00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;;
+00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0;
+00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1;
+00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2;
+00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3;
+00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4;
+00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5;
+00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6;
+00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7;
+00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8;
+00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9;
+00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA;
+00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB;
+00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC;
+00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED;
+00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE;
+00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF;
+00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0;
+00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1;
+00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2;
+00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3;
+00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4;
+00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5;
+00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6;
+00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;;
+00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8;
+00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9;
+00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA;
+00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB;
+00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC;
+00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD;
+00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE;
+00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;;
+00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0
+00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1
+00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2
+00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3
+00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4
+00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5
+00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6
+00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7
+00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8
+00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9
+00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA
+00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB
+00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC
+00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD
+00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE
+00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF
+00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0
+00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1
+00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2
+00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3
+00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4
+00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5
+00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6
+00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;;
+00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8
+00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9
+00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA
+00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB
+00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC
+00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD
+00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;;00DE;;00DE
+00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178
+0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101;
+0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100
+0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103;
+0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102
+0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105;
+0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104
+0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107;
+0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106
+0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109;
+0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108
+010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B;
+010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A
+010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D;
+010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C
+010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F;
+010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E
+0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111;
+0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110
+0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113;
+0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112
+0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115;
+0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114
+0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117;
+0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116
+0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119;
+0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118
+011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B;
+011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A
+011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D;
+011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C
+011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F;
+011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E
+0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121;
+0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120
+0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123;
+0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122
+0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125;
+0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124
+0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127;
+0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126
+0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129;
+0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128
+012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B;
+012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A
+012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D;
+012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C
+012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F;
+012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E
+0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069;
+0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049
+0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L;<compat> 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133;
+0133;LATIN SMALL LIGATURE IJ;Ll;0;L;<compat> 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132
+0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135;
+0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134
+0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137;
+0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136
+0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;;;;
+0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A;
+013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139
+013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C;
+013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B
+013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E;
+013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D
+013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L;<compat> 004C 00B7;;;;N;;;;0140;
+0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L;<compat> 006C 00B7;;;;N;;;013F;;013F
+0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142;
+0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141
+0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144;
+0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143
+0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146;
+0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145
+0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148;
+0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147
+0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L;<compat> 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;;
+014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;014B;
+014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;;014A;;014A
+014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D;
+014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C
+014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F;
+014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E
+0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151;
+0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150
+0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153;
+0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152
+0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155;
+0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154
+0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157;
+0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156
+0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159;
+0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158
+015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B;
+015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A
+015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D;
+015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C
+015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;;;015F;
+015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;;015E;;015E
+0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161;
+0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160
+0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;;;0163;
+0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;;0162;;0162
+0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165;
+0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164
+0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167;
+0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166
+0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169;
+0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168
+016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B;
+016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A
+016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D;
+016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C
+016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F;
+016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E
+0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171;
+0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170
+0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173;
+0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172
+0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175;
+0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174
+0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177;
+0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176
+0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF;
+0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A;
+017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179
+017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C;
+017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B
+017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E;
+017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D
+017F;LATIN SMALL LETTER LONG S;Ll;0;L;<compat> 0073;;;;N;;;0053;;0053
+0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;0243;;0243
+0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253;
+0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183;
+0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182
+0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185;
+0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184
+0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254;
+0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188;
+0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187
+0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;;;0256;
+018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257;
+018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C;
+018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B
+018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;;
+018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD;
+018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259;
+0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B;
+0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192;
+0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191
+0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260;
+0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263;
+0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;;01F6;;01F6
+0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269;
+0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268;
+0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199;
+0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198
+019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;023D;;023D
+019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;;;
+019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F;
+019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272;
+019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220
+019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;;;0275;
+01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1;
+01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0
+01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;;;01A3;
+01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;;01A2;;01A2
+01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5;
+01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4
+01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;;;0280;
+01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8;
+01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7
+01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283;
+01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;;
+01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;;
+01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD;
+01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC
+01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288;
+01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0;
+01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF
+01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A;
+01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B;
+01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4;
+01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3
+01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6;
+01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5
+01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292;
+01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9;
+01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8
+01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;;
+01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;;
+01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD;
+01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC
+01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;;
+01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7
+01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;;
+01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;;
+01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;;
+01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;;
+01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L;<compat> 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5
+01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L;<compat> 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6;01C5
+01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L;<compat> 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5
+01C7;LATIN CAPITAL LETTER LJ;Lu;0;L;<compat> 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8
+01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L;<compat> 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9;01C8
+01C9;LATIN SMALL LETTER LJ;Ll;0;L;<compat> 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8
+01CA;LATIN CAPITAL LETTER NJ;Lu;0;L;<compat> 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB
+01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L;<compat> 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC;01CB
+01CC;LATIN SMALL LETTER NJ;Ll;0;L;<compat> 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB
+01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE;
+01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD
+01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0;
+01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF
+01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2;
+01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1
+01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4;
+01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3
+01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6;
+01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5
+01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8;
+01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7
+01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA;
+01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9
+01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC;
+01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB
+01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E
+01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF;
+01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE
+01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1;
+01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0
+01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;;;01E3;
+01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;;01E2;;01E2
+01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5;
+01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4
+01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7;
+01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6
+01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9;
+01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8
+01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB;
+01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA
+01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED;
+01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC
+01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF;
+01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE
+01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;;
+01F1;LATIN CAPITAL LETTER DZ;Lu;0;L;<compat> 0044 005A;;;;N;;;;01F3;01F2
+01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L;<compat> 0044 007A;;;;N;;;01F1;01F3;01F2
+01F3;LATIN SMALL LETTER DZ;Ll;0;L;<compat> 0064 007A;;;;N;;;01F1;;01F2
+01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5;
+01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4
+01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195;
+01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF;
+01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9;
+01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8
+01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB;
+01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA
+01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;;;01FD;
+01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;;01FC;;01FC
+01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF;
+01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE
+0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201;
+0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200
+0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203;
+0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202
+0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205;
+0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204
+0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207;
+0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206
+0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209;
+0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208
+020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B;
+020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A
+020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D;
+020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C
+020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F;
+020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E
+0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211;
+0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210
+0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213;
+0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212
+0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215;
+0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214
+0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217;
+0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216
+0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;;;0219;
+0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;;0218;;0218
+021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;;;021B;
+021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;;021A;;021A
+021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D;
+021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C
+021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F;
+021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E
+0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E;
+0221;LATIN SMALL LETTER D WITH CURL;Ll;0;L;;;;;N;;;;;
+0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223;
+0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222
+0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225;
+0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224
+0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227;
+0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226
+0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229;
+0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228
+022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B;
+022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A
+022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D;
+022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C
+022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F;
+022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E
+0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231;
+0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230
+0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233;
+0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232
+0234;LATIN SMALL LETTER L WITH CURL;Ll;0;L;;;;;N;;;;;
+0235;LATIN SMALL LETTER N WITH CURL;Ll;0;L;;;;;N;;;;;
+0236;LATIN SMALL LETTER T WITH CURL;Ll;0;L;;;;;N;;;;;
+0237;LATIN SMALL LETTER DOTLESS J;Ll;0;L;;;;;N;;;;;
+0238;LATIN SMALL LETTER DB DIGRAPH;Ll;0;L;;;;;N;;;;;
+0239;LATIN SMALL LETTER QP DIGRAPH;Ll;0;L;;;;;N;;;;;
+023A;LATIN CAPITAL LETTER A WITH STROKE;Lu;0;L;;;;;N;;;;2C65;
+023B;LATIN CAPITAL LETTER C WITH STROKE;Lu;0;L;;;;;N;;;;023C;
+023C;LATIN SMALL LETTER C WITH STROKE;Ll;0;L;;;;;N;;;023B;;023B
+023D;LATIN CAPITAL LETTER L WITH BAR;Lu;0;L;;;;;N;;;;019A;
+023E;LATIN CAPITAL LETTER T WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;2C66;
+023F;LATIN SMALL LETTER S WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7E;;2C7E
+0240;LATIN SMALL LETTER Z WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7F;;2C7F
+0241;LATIN CAPITAL LETTER GLOTTAL STOP;Lu;0;L;;;;;N;;;;0242;
+0242;LATIN SMALL LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;0241;;0241
+0243;LATIN CAPITAL LETTER B WITH STROKE;Lu;0;L;;;;;N;;;;0180;
+0244;LATIN CAPITAL LETTER U BAR;Lu;0;L;;;;;N;;;;0289;
+0245;LATIN CAPITAL LETTER TURNED V;Lu;0;L;;;;;N;;;;028C;
+0246;LATIN CAPITAL LETTER E WITH STROKE;Lu;0;L;;;;;N;;;;0247;
+0247;LATIN SMALL LETTER E WITH STROKE;Ll;0;L;;;;;N;;;0246;;0246
+0248;LATIN CAPITAL LETTER J WITH STROKE;Lu;0;L;;;;;N;;;;0249;
+0249;LATIN SMALL LETTER J WITH STROKE;Ll;0;L;;;;;N;;;0248;;0248
+024A;LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL;Lu;0;L;;;;;N;;;;024B;
+024B;LATIN SMALL LETTER Q WITH HOOK TAIL;Ll;0;L;;;;;N;;;024A;;024A
+024C;LATIN CAPITAL LETTER R WITH STROKE;Lu;0;L;;;;;N;;;;024D;
+024D;LATIN SMALL LETTER R WITH STROKE;Ll;0;L;;;;;N;;;024C;;024C
+024E;LATIN CAPITAL LETTER Y WITH STROKE;Lu;0;L;;;;;N;;;;024F;
+024F;LATIN SMALL LETTER Y WITH STROKE;Ll;0;L;;;;;N;;;024E;;024E
+0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;2C6F;;2C6F
+0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;2C6D;;2C6D
+0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;2C70;;2C70
+0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181
+0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186
+0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;;
+0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189
+0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A
+0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;;
+0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F
+025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;;
+025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190
+025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;;;
+025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;;
+025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;;
+025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;;
+0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193
+0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;;;
+0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;;
+0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194
+0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;;
+0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;;;
+0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;;;
+0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;;
+0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197
+0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196
+026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;;;
+026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62
+026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;;;
+026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;;
+026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;;
+026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C
+0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;;
+0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;2C6E;;2C6E
+0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D
+0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;;
+0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;;
+0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F
+0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;;
+0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;;
+0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;;
+0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;;
+027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;;
+027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;;
+027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;;
+027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;2C64;;2C64
+027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;;
+027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;;
+0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;;01A6;;01A6
+0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;;
+0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;;;
+0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9
+0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;;
+0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;;
+0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;;
+0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;;;
+0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE
+0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;0244;;0244
+028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1
+028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2
+028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;0245;;0245
+028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;;
+028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;;
+028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;;
+0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;;
+0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;;
+0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7
+0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;;
+0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;;
+0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;;
+0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;;
+0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;;
+0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;;
+0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;;
+029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;;
+029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;;
+029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;;
+029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;;;
+029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;;;
+029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;;
+02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;;
+02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;;
+02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;;
+02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;;
+02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;;
+02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;;
+02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;;
+02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;;
+02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;;
+02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;;
+02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;;
+02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;;
+02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;;
+02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;;
+02AE;LATIN SMALL LETTER TURNED H WITH FISHHOOK;Ll;0;L;;;;;N;;;;;
+02AF;LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL;Ll;0;L;;;;;N;;;;;
+02B0;MODIFIER LETTER SMALL H;Lm;0;L;<super> 0068;;;;N;;;;;
+02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L;<super> 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;;
+02B2;MODIFIER LETTER SMALL J;Lm;0;L;<super> 006A;;;;N;;;;;
+02B3;MODIFIER LETTER SMALL R;Lm;0;L;<super> 0072;;;;N;;;;;
+02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L;<super> 0279;;;;N;;;;;
+02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L;<super> 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;;
+02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L;<super> 0281;;;;N;;;;;
+02B7;MODIFIER LETTER SMALL W;Lm;0;L;<super> 0077;;;;N;;;;;
+02B8;MODIFIER LETTER SMALL Y;Lm;0;L;<super> 0079;;;;N;;;;;
+02B9;MODIFIER LETTER PRIME;Lm;0;ON;;;;;N;;;;;
+02BA;MODIFIER LETTER DOUBLE PRIME;Lm;0;ON;;;;;N;;;;;
+02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;;
+02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;;
+02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;;
+02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;;
+02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;;
+02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;;
+02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;;
+02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;;
+02C7;CARON;Lm;0;ON;;;;;N;MODIFIER LETTER HACEK;;;;
+02C8;MODIFIER LETTER VERTICAL LINE;Lm;0;ON;;;;;N;;;;;
+02C9;MODIFIER LETTER MACRON;Lm;0;ON;;;;;N;;;;;
+02CA;MODIFIER LETTER ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER ACUTE;;;;
+02CB;MODIFIER LETTER GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER GRAVE;;;;
+02CC;MODIFIER LETTER LOW VERTICAL LINE;Lm;0;ON;;;;;N;;;;;
+02CD;MODIFIER LETTER LOW MACRON;Lm;0;ON;;;;;N;;;;;
+02CE;MODIFIER LETTER LOW GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;;
+02CF;MODIFIER LETTER LOW ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;;
+02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;;
+02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;;
+02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;;
+02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;;
+02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;;
+02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;;
+02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;;
+02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;;
+02D8;BREVE;Sk;0;ON;<compat> 0020 0306;;;;N;SPACING BREVE;;;;
+02D9;DOT ABOVE;Sk;0;ON;<compat> 0020 0307;;;;N;SPACING DOT ABOVE;;;;
+02DA;RING ABOVE;Sk;0;ON;<compat> 0020 030A;;;;N;SPACING RING ABOVE;;;;
+02DB;OGONEK;Sk;0;ON;<compat> 0020 0328;;;;N;SPACING OGONEK;;;;
+02DC;SMALL TILDE;Sk;0;ON;<compat> 0020 0303;;;;N;SPACING TILDE;;;;
+02DD;DOUBLE ACUTE ACCENT;Sk;0;ON;<compat> 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;;
+02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;;
+02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;;
+02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L;<super> 0263;;;;N;;;;;
+02E1;MODIFIER LETTER SMALL L;Lm;0;L;<super> 006C;;;;N;;;;;
+02E2;MODIFIER LETTER SMALL S;Lm;0;L;<super> 0073;;;;N;;;;;
+02E3;MODIFIER LETTER SMALL X;Lm;0;L;<super> 0078;;;;N;;;;;
+02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L;<super> 0295;;;;N;;;;;
+02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;;
+02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;;
+02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;;
+02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;;
+02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;;
+02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;;
+02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;;
+02EC;MODIFIER LETTER VOICING;Lm;0;ON;;;;;N;;;;;
+02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;;
+02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;;
+02EF;MODIFIER LETTER LOW DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02F0;MODIFIER LETTER LOW UP ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02F1;MODIFIER LETTER LOW LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02F2;MODIFIER LETTER LOW RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;;
+02F3;MODIFIER LETTER LOW RING;Sk;0;ON;;;;;N;;;;;
+02F4;MODIFIER LETTER MIDDLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;;
+02F5;MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;;
+02F6;MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT;Sk;0;ON;;;;;N;;;;;
+02F7;MODIFIER LETTER LOW TILDE;Sk;0;ON;;;;;N;;;;;
+02F8;MODIFIER LETTER RAISED COLON;Sk;0;ON;;;;;N;;;;;
+02F9;MODIFIER LETTER BEGIN HIGH TONE;Sk;0;ON;;;;;N;;;;;
+02FA;MODIFIER LETTER END HIGH TONE;Sk;0;ON;;;;;N;;;;;
+02FB;MODIFIER LETTER BEGIN LOW TONE;Sk;0;ON;;;;;N;;;;;
+02FC;MODIFIER LETTER END LOW TONE;Sk;0;ON;;;;;N;;;;;
+02FD;MODIFIER LETTER SHELF;Sk;0;ON;;;;;N;;;;;
+02FE;MODIFIER LETTER OPEN SHELF;Sk;0;ON;;;;;N;;;;;
+02FF;MODIFIER LETTER LOW LEFT ARROW;Sk;0;ON;;;;;N;;;;;
+0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;;
+0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;;;;
+0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;;
+0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;;
+0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;;
+0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;;
+0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;;;;
+0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;;
+0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;;;;
+0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;;
+030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;;
+030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;;
+030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;;
+030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;;
+030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;;
+030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;;
+0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;;
+0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;;
+0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;;
+0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;;;;
+0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;;;;
+0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;;
+0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;;
+0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;;
+0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;;
+0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;;
+031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;;
+031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;;
+031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;;
+031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;;
+031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;;
+031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;;
+0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;;
+0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;;
+0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;;
+0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;;
+0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;;
+0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;;
+0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;;
+0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;;
+0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;;
+0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;;
+032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;;
+032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;;
+032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;;
+032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;;
+032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;;
+032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;;
+0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;;
+0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;;
+0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;;
+0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;;
+0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;;
+0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;;
+0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;;
+0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;;
+0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;;
+0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;;
+033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;;
+033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;;
+033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;;
+033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;;
+033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;;
+033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;;
+0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;;;;
+0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;;;;
+0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;;
+0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;;
+0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;;
+0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399
+0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;;
+0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;;
+0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;;
+0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;;
+034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;;
+034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;;
+034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;;
+034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
+034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
+034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;;
+0350;COMBINING RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;;
+0351;COMBINING LEFT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;;
+0352;COMBINING FERMATA;Mn;230;NSM;;;;;N;;;;;
+0353;COMBINING X BELOW;Mn;220;NSM;;;;;N;;;;;
+0354;COMBINING LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
+0355;COMBINING RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
+0356;COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
+0357;COMBINING RIGHT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;;
+0358;COMBINING DOT ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;;
+0359;COMBINING ASTERISK BELOW;Mn;220;NSM;;;;;N;;;;;
+035A;COMBINING DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;;
+035B;COMBINING ZIGZAG ABOVE;Mn;230;NSM;;;;;N;;;;;
+035C;COMBINING DOUBLE BREVE BELOW;Mn;233;NSM;;;;;N;;;;;
+035D;COMBINING DOUBLE BREVE;Mn;234;NSM;;;;;N;;;;;
+035E;COMBINING DOUBLE MACRON;Mn;234;NSM;;;;;N;;;;;
+035F;COMBINING DOUBLE MACRON BELOW;Mn;233;NSM;;;;;N;;;;;
+0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;;
+0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;;
+0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;;
+0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;;
+0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;;
+0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;;
+0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;;
+0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;;
+0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;;
+0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;;
+036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;;
+036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;;
+036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;;
+036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;;
+036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;;
+036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;;
+0370;GREEK CAPITAL LETTER HETA;Lu;0;L;;;;;N;;;;0371;
+0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370
+0372;GREEK CAPITAL LETTER ARCHAIC SAMPI;Lu;0;L;;;;;N;;;;0373;
+0373;GREEK SMALL LETTER ARCHAIC SAMPI;Ll;0;L;;;;;N;;;0372;;0372
+0374;GREEK NUMERAL SIGN;Lm;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;;;;
+0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;;;;
+0376;GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA;Lu;0;L;;;;;N;;;;0377;
+0377;GREEK SMALL LETTER PAMPHYLIAN DIGAMMA;Ll;0;L;;;;;N;;;0376;;0376
+037A;GREEK YPOGEGRAMMENI;Lm;0;L;<compat> 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;;
+037B;GREEK SMALL REVERSED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FD;;03FD
+037C;GREEK SMALL DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FE;;03FE
+037D;GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FF;;03FF
+037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;;;;
+0384;GREEK TONOS;Sk;0;ON;<compat> 0020 0301;;;;N;GREEK SPACING TONOS;;;;
+0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;;
+0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC;
+0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;;
+0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD;
+0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE;
+038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF;
+038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC;
+038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD;
+038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE;
+0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;;
+0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1;
+0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2;
+0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3;
+0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4;
+0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5;
+0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6;
+0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7;
+0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;
+0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9;
+039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA;
+039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB;
+039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC;
+039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD;
+039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE;
+039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF;
+03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0;
+03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1;
+03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3;
+03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4;
+03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5;
+03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6;
+03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7;
+03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8;
+03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9;
+03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA;
+03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB;
+03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386
+03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388
+03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389
+03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A
+03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;;
+03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391
+03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392
+03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393
+03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394
+03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395
+03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396
+03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397
+03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398
+03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399
+03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A
+03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B
+03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C
+03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D
+03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E
+03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F
+03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0
+03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1
+03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3
+03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3
+03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4
+03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5
+03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6
+03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7
+03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8
+03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9
+03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA
+03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB
+03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C
+03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E
+03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F
+03CF;GREEK CAPITAL KAI SYMBOL;Lu;0;L;;;;;N;;;;03D7;
+03D0;GREEK BETA SYMBOL;Ll;0;L;<compat> 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392
+03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398
+03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L;<compat> 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;;
+03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;;
+03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;;
+03D5;GREEK PHI SYMBOL;Ll;0;L;<compat> 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6
+03D6;GREEK PI SYMBOL;Ll;0;L;<compat> 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0
+03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;03CF;;03CF
+03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;;;03D9;
+03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;;03D8;;03D8
+03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB;
+03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA
+03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD;
+03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC
+03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF;
+03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE
+03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1;
+03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0
+03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3;
+03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2
+03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5;
+03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4
+03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7;
+03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6
+03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9;
+03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8
+03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB;
+03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA
+03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED;
+03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC
+03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF;
+03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE
+03F0;GREEK KAPPA SYMBOL;Ll;0;L;<compat> 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A
+03F1;GREEK RHO SYMBOL;Ll;0;L;<compat> 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1
+03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L;<compat> 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03F9;;03F9
+03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;;;
+03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8;
+03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L;<compat> 03B5;;;;N;;;0395;;0395
+03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;;
+03F7;GREEK CAPITAL LETTER SHO;Lu;0;L;;;;;N;;;;03F8;
+03F8;GREEK SMALL LETTER SHO;Ll;0;L;;;;;N;;;03F7;;03F7
+03F9;GREEK CAPITAL LUNATE SIGMA SYMBOL;Lu;0;L;<compat> 03A3;;;;N;;;;03F2;
+03FA;GREEK CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;03FB;
+03FB;GREEK SMALL LETTER SAN;Ll;0;L;;;;;N;;;03FA;;03FA
+03FC;GREEK RHO WITH STROKE SYMBOL;Ll;0;L;;;;;N;;;;;
+03FD;GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037B;
+03FE;GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037C;
+03FF;GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037D;
+0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450;
+0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451;
+0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;;;0452;
+0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453;
+0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454;
+0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455;
+0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456;
+0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;;;0457;
+0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458;
+0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459;
+040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A;
+040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;;;045B;
+040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C;
+040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D;
+040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;;;045E;
+040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F;
+0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430;
+0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431;
+0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432;
+0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433;
+0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434;
+0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435;
+0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436;
+0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437;
+0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438;
+0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439;
+041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A;
+041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B;
+041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C;
+041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D;
+041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E;
+041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F;
+0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440;
+0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441;
+0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442;
+0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443;
+0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444;
+0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445;
+0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446;
+0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447;
+0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448;
+0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449;
+042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A;
+042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B;
+042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C;
+042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D;
+042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E;
+042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F;
+0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410
+0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411
+0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412
+0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413
+0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414
+0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415
+0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416
+0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417
+0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418
+0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419
+043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A
+043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B
+043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C
+043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D
+043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E
+043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F
+0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420
+0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421
+0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422
+0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423
+0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424
+0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425
+0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426
+0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427
+0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428
+0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429
+044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A
+044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B
+044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C
+044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D
+044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E
+044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F
+0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400
+0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401
+0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;;0402;;0402
+0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403
+0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404
+0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405
+0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406
+0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;;0407;;0407
+0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408
+0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409
+045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A
+045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;;040B;;040B
+045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C
+045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D
+045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;;040E;;040E
+045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F
+0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461;
+0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460
+0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463;
+0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462
+0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465;
+0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464
+0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467;
+0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466
+0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469;
+0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468
+046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B;
+046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A
+046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D;
+046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C
+046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F;
+046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E
+0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471;
+0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470
+0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473;
+0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472
+0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475;
+0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474
+0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477;
+0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476
+0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479;
+0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478
+047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B;
+047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A
+047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D;
+047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C
+047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F;
+047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E
+0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481;
+0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480
+0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;;
+0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;;
+0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;;
+0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;;
+0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;;
+0487;COMBINING CYRILLIC POKRYTIE;Mn;230;NSM;;;;;N;;;;;
+0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;;
+0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
+048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B;
+048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A
+048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D;
+048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C
+048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F;
+048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E
+0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491;
+0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490
+0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493;
+0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492
+0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495;
+0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494
+0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497;
+0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496
+0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499;
+0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498
+049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B;
+049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A
+049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D;
+049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C
+049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F;
+049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E
+04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1;
+04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0
+04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3;
+04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2
+04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5;
+04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4
+04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;;;04A7;
+04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;;04A6;;04A6
+04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9;
+04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8
+04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB;
+04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA
+04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD;
+04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC
+04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF;
+04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE
+04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1;
+04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0
+04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3;
+04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2
+04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;;;04B5;
+04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;;04B4;;04B4
+04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7;
+04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6
+04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9;
+04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8
+04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB;
+04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA
+04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD;
+04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC
+04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF;
+04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE
+04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;04CF;
+04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2;
+04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1
+04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4;
+04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3
+04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6;
+04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5
+04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8;
+04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7
+04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA;
+04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9
+04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC;
+04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB
+04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE;
+04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD
+04CF;CYRILLIC SMALL LETTER PALOCHKA;Ll;0;L;;;;;N;;;04C0;;04C0
+04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1;
+04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0
+04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3;
+04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2
+04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5;
+04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4
+04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7;
+04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6
+04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9;
+04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8
+04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB;
+04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA
+04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD;
+04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC
+04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF;
+04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE
+04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1;
+04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0
+04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3;
+04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2
+04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5;
+04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4
+04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7;
+04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6
+04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9;
+04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8
+04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB;
+04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA
+04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED;
+04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC
+04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF;
+04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE
+04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1;
+04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0
+04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3;
+04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2
+04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5;
+04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4
+04F6;CYRILLIC CAPITAL LETTER GHE WITH DESCENDER;Lu;0;L;;;;;N;;;;04F7;
+04F7;CYRILLIC SMALL LETTER GHE WITH DESCENDER;Ll;0;L;;;;;N;;;04F6;;04F6
+04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9;
+04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8
+04FA;CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK;Lu;0;L;;;;;N;;;;04FB;
+04FB;CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK;Ll;0;L;;;;;N;;;04FA;;04FA
+04FC;CYRILLIC CAPITAL LETTER HA WITH HOOK;Lu;0;L;;;;;N;;;;04FD;
+04FD;CYRILLIC SMALL LETTER HA WITH HOOK;Ll;0;L;;;;;N;;;04FC;;04FC
+04FE;CYRILLIC CAPITAL LETTER HA WITH STROKE;Lu;0;L;;;;;N;;;;04FF;
+04FF;CYRILLIC SMALL LETTER HA WITH STROKE;Ll;0;L;;;;;N;;;04FE;;04FE
+0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501;
+0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500
+0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503;
+0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502
+0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505;
+0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504
+0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507;
+0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506
+0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509;
+0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508
+050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B;
+050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A
+050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D;
+050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C
+050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F;
+050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E
+0510;CYRILLIC CAPITAL LETTER REVERSED ZE;Lu;0;L;;;;;N;;;;0511;
+0511;CYRILLIC SMALL LETTER REVERSED ZE;Ll;0;L;;;;;N;;;0510;;0510
+0512;CYRILLIC CAPITAL LETTER EL WITH HOOK;Lu;0;L;;;;;N;;;;0513;
+0513;CYRILLIC SMALL LETTER EL WITH HOOK;Ll;0;L;;;;;N;;;0512;;0512
+0514;CYRILLIC CAPITAL LETTER LHA;Lu;0;L;;;;;N;;;;0515;
+0515;CYRILLIC SMALL LETTER LHA;Ll;0;L;;;;;N;;;0514;;0514
+0516;CYRILLIC CAPITAL LETTER RHA;Lu;0;L;;;;;N;;;;0517;
+0517;CYRILLIC SMALL LETTER RHA;Ll;0;L;;;;;N;;;0516;;0516
+0518;CYRILLIC CAPITAL LETTER YAE;Lu;0;L;;;;;N;;;;0519;
+0519;CYRILLIC SMALL LETTER YAE;Ll;0;L;;;;;N;;;0518;;0518
+051A;CYRILLIC CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;051B;
+051B;CYRILLIC SMALL LETTER QA;Ll;0;L;;;;;N;;;051A;;051A
+051C;CYRILLIC CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;051D;
+051D;CYRILLIC SMALL LETTER WE;Ll;0;L;;;;;N;;;051C;;051C
+051E;CYRILLIC CAPITAL LETTER ALEUT KA;Lu;0;L;;;;;N;;;;051F;
+051F;CYRILLIC SMALL LETTER ALEUT KA;Ll;0;L;;;;;N;;;051E;;051E
+0520;CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0521;
+0521;CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0520;;0520
+0522;CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0523;
+0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522
+0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525;
+0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524
+0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561;
+0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562;
+0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563;
+0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564;
+0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565;
+0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566;
+0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567;
+0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568;
+0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569;
+053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A;
+053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B;
+053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C;
+053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D;
+053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E;
+053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F;
+0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570;
+0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571;
+0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572;
+0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573;
+0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574;
+0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575;
+0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576;
+0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577;
+0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578;
+0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579;
+054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A;
+054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B;
+054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C;
+054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D;
+054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E;
+054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F;
+0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580;
+0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581;
+0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582;
+0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583;
+0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584;
+0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585;
+0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586;
+0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;;
+055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;;
+055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;;
+055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;;
+055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;;
+055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;;
+055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;;
+0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531
+0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532
+0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533
+0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534
+0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535
+0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536
+0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537
+0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538
+0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539
+056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A
+056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B
+056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C
+056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D
+056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E
+056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F
+0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540
+0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541
+0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542
+0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543
+0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544
+0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545
+0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546
+0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547
+0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548
+0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549
+057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A
+057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B
+057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C
+057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D
+057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E
+057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F
+0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550
+0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551
+0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552
+0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553
+0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554
+0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555
+0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556
+0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L;<compat> 0565 0582;;;;N;;;;;
+0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;;
+058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;;
+0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;;
+0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;;
+0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;;
+0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;;
+0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;;
+0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;;;;
+0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;;
+0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;;;;
+0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;;
+059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;;
+059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;;
+059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;;
+059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;;
+059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;;
+059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;;
+05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;;
+05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;;
+05A2;HEBREW ACCENT ATNAH HAFUKH;Mn;220;NSM;;;;;N;;;;;
+05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;;
+05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;;
+05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;;;;
+05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;;
+05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;;
+05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;;;;
+05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;;
+05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;;;;
+05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;;
+05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;;
+05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;;
+05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;;
+05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;;
+05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;;
+05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;;
+05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;;
+05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;;
+05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;;
+05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;;
+05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;;
+05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;;
+05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;;
+05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;;
+05BA;HEBREW POINT HOLAM HASER FOR VAV;Mn;19;NSM;;;;;N;;;;;
+05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;;
+05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;;;;
+05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;;;;
+05BE;HEBREW PUNCTUATION MAQAF;Pd;0;R;;;;;N;;;;;
+05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;;
+05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;;;;
+05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;;
+05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;;
+05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;;;;
+05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;;
+05C5;HEBREW MARK LOWER DOT;Mn;220;NSM;;;;;N;;;;;
+05C6;HEBREW PUNCTUATION NUN HAFUKHA;Po;0;R;;;;;N;;;;;
+05C7;HEBREW POINT QAMATS QATAN;Mn;18;NSM;;;;;N;;;;;
+05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;;
+05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;;
+05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;;
+05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;;
+05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;;
+05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;;
+05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
+05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;;
+05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;;
+05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;;
+05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;;
+05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;;
+05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;;
+05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;;
+05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;;
+05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;;
+05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;;
+05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
+05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;;
+05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;;
+05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;;
+05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;;
+05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;;
+05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;;
+05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;;
+05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;;
+05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;;
+05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;;
+05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;;
+05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;;
+05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;;
+05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;;
+0600;ARABIC NUMBER SIGN;Cf;0;AN;;;;;N;;;;;
+0601;ARABIC SIGN SANAH;Cf;0;AN;;;;;N;;;;;
+0602;ARABIC FOOTNOTE MARKER;Cf;0;AN;;;;;N;;;;;
+0603;ARABIC SIGN SAFHA;Cf;0;AN;;;;;N;;;;;
+0606;ARABIC-INDIC CUBE ROOT;Sm;0;ON;;;;;N;;;;;
+0607;ARABIC-INDIC FOURTH ROOT;Sm;0;ON;;;;;N;;;;;
+0608;ARABIC RAY;Sm;0;AL;;;;;N;;;;;
+0609;ARABIC-INDIC PER MILLE SIGN;Po;0;ET;;;;;N;;;;;
+060A;ARABIC-INDIC PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;;
+060B;AFGHANI SIGN;Sc;0;AL;;;;;N;;;;;
+060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;;
+060D;ARABIC DATE SEPARATOR;Po;0;AL;;;;;N;;;;;
+060E;ARABIC POETIC VERSE SIGN;So;0;ON;;;;;N;;;;;
+060F;ARABIC SIGN MISRA;So;0;ON;;;;;N;;;;;
+0610;ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM;Mn;230;NSM;;;;;N;;;;;
+0611;ARABIC SIGN ALAYHE ASSALLAM;Mn;230;NSM;;;;;N;;;;;
+0612;ARABIC SIGN RAHMATULLAH ALAYHE;Mn;230;NSM;;;;;N;;;;;
+0613;ARABIC SIGN RADI ALLAHOU ANHU;Mn;230;NSM;;;;;N;;;;;
+0614;ARABIC SIGN TAKHALLUS;Mn;230;NSM;;;;;N;;;;;
+0615;ARABIC SMALL HIGH TAH;Mn;230;NSM;;;;;N;;;;;
+0616;ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH;Mn;230;NSM;;;;;N;;;;;
+0617;ARABIC SMALL HIGH ZAIN;Mn;230;NSM;;;;;N;;;;;
+0618;ARABIC SMALL FATHA;Mn;30;NSM;;;;;N;;;;;
+0619;ARABIC SMALL DAMMA;Mn;31;NSM;;;;;N;;;;;
+061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;;
+061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;;
+061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;;
+061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;;
+0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;;
+0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;;
+0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;;
+0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;;
+0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;;
+0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;;
+0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;;
+0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;;
+0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;;
+062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;;
+062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;;
+062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;;
+062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;;
+062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;;
+062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;;
+0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;;
+0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;;
+0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;;
+0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;;
+0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;;
+0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;;
+0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;;
+0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;;
+0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;;
+0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;;
+063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;;
+063B;ARABIC LETTER KEHEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+063C;ARABIC LETTER KEHEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+063D;ARABIC LETTER FARSI YEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
+063E;ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+063F;ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;;
+0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;;
+0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;;
+0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;;
+0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;;
+0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;;
+0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;;
+0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;;
+0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;;
+0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;;
+064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;;
+064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;;
+064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;;
+064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;;
+064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;;
+064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;;
+0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;;
+0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;;
+0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;;
+0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;;
+0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;;
+0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;;
+0656;ARABIC SUBSCRIPT ALEF;Mn;220;NSM;;;;;N;;;;;
+0657;ARABIC INVERTED DAMMA;Mn;230;NSM;;;;;N;;;;;
+0658;ARABIC MARK NOON GHUNNA;Mn;230;NSM;;;;;N;;;;;
+0659;ARABIC ZWARAKAY;Mn;230;NSM;;;;;N;;;;;
+065A;ARABIC VOWEL SIGN SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;;
+065B;ARABIC VOWEL SIGN INVERTED SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;;
+065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;;
+065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;;
+065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;;
+0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;;
+0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;;
+0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;;
+0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;;
+0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;;
+0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;;
+0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;;
+0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;;
+0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;;
+0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;;
+066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;;
+066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;;
+066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;;
+066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;;
+066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;;
+066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;;
+0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;;
+0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;;
+0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;;
+0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;;
+0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;;
+0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL;<compat> 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;;
+0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL;<compat> 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;;
+0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL;<compat> 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;;
+0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL;<compat> 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;;
+0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;;
+067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;;
+067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;;
+067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;;
+067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;;
+067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;;
+067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;;
+0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;;
+0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;;
+0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;;
+0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;;
+0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;;
+0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;;
+0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;;
+0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;;
+0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;;
+0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;;
+068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;;
+068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;;
+068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;;
+068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;;
+068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;;
+0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;;
+0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;;
+0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;;
+0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;;
+0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;;
+0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;;
+0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;;
+0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;;
+0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;;
+069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;;
+06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;;
+06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;;
+06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;;
+06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;;
+06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;;
+06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;;
+06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;;
+06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;;
+06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;;
+06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;;
+06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;;
+06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;;;;
+06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;;
+06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;;
+06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;;
+06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;;
+06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;;
+06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;;
+06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;;
+06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;;
+06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;;
+06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;;
+06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;;
+06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;;
+06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;;
+06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;;
+06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;;
+06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;;
+06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;;
+06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;;
+06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;;
+06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;;
+06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;;
+06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;;
+06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;;;;
+06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;;
+06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;;
+06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;;
+06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;;
+06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;;
+06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;;
+06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;;
+06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;;
+06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;;
+06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;;
+06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;;
+06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;;
+06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;;
+06DE;ARABIC START OF RUB EL HIZB;Me;0;NSM;;;;;N;;;;;
+06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;;
+06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;;
+06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;;
+06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;;
+06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;;
+06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;;
+06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;;
+06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;;
+06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;;
+06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;;
+06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;;
+06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;;
+06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;;
+06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;;
+06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;;
+06EE;ARABIC LETTER DAL WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
+06EF;ARABIC LETTER REH WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
+06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;;
+06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;;
+06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;;
+06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;;
+06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;;
+06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;;
+06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;;
+06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;;
+06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;;
+06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;;
+06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;;
+06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;;
+06FF;ARABIC LETTER HEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
+0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;;
+0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;;
+0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;;
+0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;;
+0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;;
+0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;;
+0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;;
+0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;;
+0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;;
+0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;;
+070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;;
+070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;;
+070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;;
+070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;;
+070F;SYRIAC ABBREVIATION MARK;Cf;0;BN;;;;;N;;;;;
+0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;;
+0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;;
+0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;;
+0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;;
+0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;;
+0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;;
+0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;;
+0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;;
+0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;;
+0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;;
+071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;;
+071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;;
+071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;;
+071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;;
+071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;;
+071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;;
+0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;;
+0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;;
+0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;;
+0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;;
+0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;;
+0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;;
+0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;;
+0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;;
+0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;;
+0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;;
+072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;;
+072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;;
+072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;;
+072D;SYRIAC LETTER PERSIAN BHETH;Lo;0;AL;;;;;N;;;;;
+072E;SYRIAC LETTER PERSIAN GHAMAL;Lo;0;AL;;;;;N;;;;;
+072F;SYRIAC LETTER PERSIAN DHALATH;Lo;0;AL;;;;;N;;;;;
+0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;;
+0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;;
+0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;;
+0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;;
+0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;;
+0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;;
+0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;;
+0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;;
+0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;;
+0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;;
+073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;;
+073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;;
+073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;;
+073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;;
+073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;;
+073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;;
+0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;;
+0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;;
+0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;;
+0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;;
+0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
+0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;;
+0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
+0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;;
+0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;;
+0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;;
+074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;;
+074D;SYRIAC LETTER SOGDIAN ZHAIN;Lo;0;AL;;;;;N;;;;;
+074E;SYRIAC LETTER SOGDIAN KHAPH;Lo;0;AL;;;;;N;;;;;
+074F;SYRIAC LETTER SOGDIAN FE;Lo;0;AL;;;;;N;;;;;
+0750;ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW;Lo;0;AL;;;;;N;;;;;
+0751;ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+0752;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
+0753;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+0754;ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+0755;ARABIC LETTER BEH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
+0756;ARABIC LETTER BEH WITH SMALL V;Lo;0;AL;;;;;N;;;;;
+0757;ARABIC LETTER HAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+0758;ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
+0759;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;;
+075A;ARABIC LETTER DAL WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
+075B;ARABIC LETTER REH WITH STROKE;Lo;0;AL;;;;;N;;;;;
+075C;ARABIC LETTER SEEN WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+075D;ARABIC LETTER AIN WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+075E;ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE;Lo;0;AL;;;;;N;;;;;
+075F;ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;;
+0760;ARABIC LETTER FEH WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+0761;ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
+0762;ARABIC LETTER KEHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+0763;ARABIC LETTER KEHEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+0764;ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;;
+0765;ARABIC LETTER MEEM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+0766;ARABIC LETTER MEEM WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+0767;ARABIC LETTER NOON WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+0768;ARABIC LETTER NOON WITH SMALL TAH;Lo;0;AL;;;;;N;;;;;
+0769;ARABIC LETTER NOON WITH SMALL V;Lo;0;AL;;;;;N;;;;;
+076A;ARABIC LETTER LAM WITH BAR;Lo;0;AL;;;;;N;;;;;
+076B;ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;;
+076C;ARABIC LETTER REH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;;
+076D;ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;;
+076E;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW;Lo;0;AL;;;;;N;;;;;
+076F;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;;
+0770;ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;;
+0771;ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;;
+0772;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;;
+0773;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
+0774;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
+0775;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
+0776;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
+0777;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;;
+0778;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
+0779;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
+077A;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;;
+077B;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;;
+077C;ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;;
+077D;ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE;Lo;0;AL;;;;;N;;;;;
+077E;ARABIC LETTER SEEN WITH INVERTED V;Lo;0;AL;;;;;N;;;;;
+077F;ARABIC LETTER KAF WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
+0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;;
+0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;;
+0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;;
+0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;;
+0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;;
+0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;;
+0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;;
+0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;;
+0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;;
+0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;;
+078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;;
+078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;;
+078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;;
+078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;;
+078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;;
+078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;;
+0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;;
+0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;;
+0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;;
+0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;;
+0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;;
+0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;;
+0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;;
+0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;;
+0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;;
+0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;;
+079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;;
+079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;;
+079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;;
+079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;;
+079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;;
+079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;;
+07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;;
+07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;;
+07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;;
+07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;;
+07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;;
+07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;;
+07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;;
+07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;;
+07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;;
+07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;;
+07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;;
+07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;;
+07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;;
+07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;;
+07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;;
+07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;;
+07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;;
+07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;;
+07C0;NKO DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;;
+07C1;NKO DIGIT ONE;Nd;0;R;;1;1;1;N;;;;;
+07C2;NKO DIGIT TWO;Nd;0;R;;2;2;2;N;;;;;
+07C3;NKO DIGIT THREE;Nd;0;R;;3;3;3;N;;;;;
+07C4;NKO DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;;
+07C5;NKO DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;;
+07C6;NKO DIGIT SIX;Nd;0;R;;6;6;6;N;;;;;
+07C7;NKO DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;;
+07C8;NKO DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;;
+07C9;NKO DIGIT NINE;Nd;0;R;;9;9;9;N;;;;;
+07CA;NKO LETTER A;Lo;0;R;;;;;N;;;;;
+07CB;NKO LETTER EE;Lo;0;R;;;;;N;;;;;
+07CC;NKO LETTER I;Lo;0;R;;;;;N;;;;;
+07CD;NKO LETTER E;Lo;0;R;;;;;N;;;;;
+07CE;NKO LETTER U;Lo;0;R;;;;;N;;;;;
+07CF;NKO LETTER OO;Lo;0;R;;;;;N;;;;;
+07D0;NKO LETTER O;Lo;0;R;;;;;N;;;;;
+07D1;NKO LETTER DAGBASINNA;Lo;0;R;;;;;N;;;;;
+07D2;NKO LETTER N;Lo;0;R;;;;;N;;;;;
+07D3;NKO LETTER BA;Lo;0;R;;;;;N;;;;;
+07D4;NKO LETTER PA;Lo;0;R;;;;;N;;;;;
+07D5;NKO LETTER TA;Lo;0;R;;;;;N;;;;;
+07D6;NKO LETTER JA;Lo;0;R;;;;;N;;;;;
+07D7;NKO LETTER CHA;Lo;0;R;;;;;N;;;;;
+07D8;NKO LETTER DA;Lo;0;R;;;;;N;;;;;
+07D9;NKO LETTER RA;Lo;0;R;;;;;N;;;;;
+07DA;NKO LETTER RRA;Lo;0;R;;;;;N;;;;;
+07DB;NKO LETTER SA;Lo;0;R;;;;;N;;;;;
+07DC;NKO LETTER GBA;Lo;0;R;;;;;N;;;;;
+07DD;NKO LETTER FA;Lo;0;R;;;;;N;;;;;
+07DE;NKO LETTER KA;Lo;0;R;;;;;N;;;;;
+07DF;NKO LETTER LA;Lo;0;R;;;;;N;;;;;
+07E0;NKO LETTER NA WOLOSO;Lo;0;R;;;;;N;;;;;
+07E1;NKO LETTER MA;Lo;0;R;;;;;N;;;;;
+07E2;NKO LETTER NYA;Lo;0;R;;;;;N;;;;;
+07E3;NKO LETTER NA;Lo;0;R;;;;;N;;;;;
+07E4;NKO LETTER HA;Lo;0;R;;;;;N;;;;;
+07E5;NKO LETTER WA;Lo;0;R;;;;;N;;;;;
+07E6;NKO LETTER YA;Lo;0;R;;;;;N;;;;;
+07E7;NKO LETTER NYA WOLOSO;Lo;0;R;;;;;N;;;;;
+07E8;NKO LETTER JONA JA;Lo;0;R;;;;;N;;;;;
+07E9;NKO LETTER JONA CHA;Lo;0;R;;;;;N;;;;;
+07EA;NKO LETTER JONA RA;Lo;0;R;;;;;N;;;;;
+07EB;NKO COMBINING SHORT HIGH TONE;Mn;230;NSM;;;;;N;;;;;
+07EC;NKO COMBINING SHORT LOW TONE;Mn;230;NSM;;;;;N;;;;;
+07ED;NKO COMBINING SHORT RISING TONE;Mn;230;NSM;;;;;N;;;;;
+07EE;NKO COMBINING LONG DESCENDING TONE;Mn;230;NSM;;;;;N;;;;;
+07EF;NKO COMBINING LONG HIGH TONE;Mn;230;NSM;;;;;N;;;;;
+07F0;NKO COMBINING LONG LOW TONE;Mn;230;NSM;;;;;N;;;;;
+07F1;NKO COMBINING LONG RISING TONE;Mn;230;NSM;;;;;N;;;;;
+07F2;NKO COMBINING NASALIZATION MARK;Mn;220;NSM;;;;;N;;;;;
+07F3;NKO COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;;
+07F4;NKO HIGH TONE APOSTROPHE;Lm;0;R;;;;;N;;;;;
+07F5;NKO LOW TONE APOSTROPHE;Lm;0;R;;;;;N;;;;;
+07F6;NKO SYMBOL OO DENNEN;So;0;ON;;;;;N;;;;;
+07F7;NKO SYMBOL GBAKURUNEN;Po;0;ON;;;;;N;;;;;
+07F8;NKO COMMA;Po;0;ON;;;;;N;;;;;
+07F9;NKO EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
+07FA;NKO LAJANYALAN;Lm;0;R;;;;;N;;;;;
+0800;SAMARITAN LETTER ALAF;Lo;0;R;;;;;N;;;;;
+0801;SAMARITAN LETTER BIT;Lo;0;R;;;;;N;;;;;
+0802;SAMARITAN LETTER GAMAN;Lo;0;R;;;;;N;;;;;
+0803;SAMARITAN LETTER DALAT;Lo;0;R;;;;;N;;;;;
+0804;SAMARITAN LETTER IY;Lo;0;R;;;;;N;;;;;
+0805;SAMARITAN LETTER BAA;Lo;0;R;;;;;N;;;;;
+0806;SAMARITAN LETTER ZEN;Lo;0;R;;;;;N;;;;;
+0807;SAMARITAN LETTER IT;Lo;0;R;;;;;N;;;;;
+0808;SAMARITAN LETTER TIT;Lo;0;R;;;;;N;;;;;
+0809;SAMARITAN LETTER YUT;Lo;0;R;;;;;N;;;;;
+080A;SAMARITAN LETTER KAAF;Lo;0;R;;;;;N;;;;;
+080B;SAMARITAN LETTER LABAT;Lo;0;R;;;;;N;;;;;
+080C;SAMARITAN LETTER MIM;Lo;0;R;;;;;N;;;;;
+080D;SAMARITAN LETTER NUN;Lo;0;R;;;;;N;;;;;
+080E;SAMARITAN LETTER SINGAAT;Lo;0;R;;;;;N;;;;;
+080F;SAMARITAN LETTER IN;Lo;0;R;;;;;N;;;;;
+0810;SAMARITAN LETTER FI;Lo;0;R;;;;;N;;;;;
+0811;SAMARITAN LETTER TSAADIY;Lo;0;R;;;;;N;;;;;
+0812;SAMARITAN LETTER QUF;Lo;0;R;;;;;N;;;;;
+0813;SAMARITAN LETTER RISH;Lo;0;R;;;;;N;;;;;
+0814;SAMARITAN LETTER SHAN;Lo;0;R;;;;;N;;;;;
+0815;SAMARITAN LETTER TAAF;Lo;0;R;;;;;N;;;;;
+0816;SAMARITAN MARK IN;Mn;230;NSM;;;;;N;;;;;
+0817;SAMARITAN MARK IN-ALAF;Mn;230;NSM;;;;;N;;;;;
+0818;SAMARITAN MARK OCCLUSION;Mn;230;NSM;;;;;N;;;;;
+0819;SAMARITAN MARK DAGESH;Mn;230;NSM;;;;;N;;;;;
+081A;SAMARITAN MODIFIER LETTER EPENTHETIC YUT;Lm;0;R;;;;;N;;;;;
+081B;SAMARITAN MARK EPENTHETIC YUT;Mn;230;NSM;;;;;N;;;;;
+081C;SAMARITAN VOWEL SIGN LONG E;Mn;230;NSM;;;;;N;;;;;
+081D;SAMARITAN VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;;
+081E;SAMARITAN VOWEL SIGN OVERLONG AA;Mn;230;NSM;;;;;N;;;;;
+081F;SAMARITAN VOWEL SIGN LONG AA;Mn;230;NSM;;;;;N;;;;;
+0820;SAMARITAN VOWEL SIGN AA;Mn;230;NSM;;;;;N;;;;;
+0821;SAMARITAN VOWEL SIGN OVERLONG A;Mn;230;NSM;;;;;N;;;;;
+0822;SAMARITAN VOWEL SIGN LONG A;Mn;230;NSM;;;;;N;;;;;
+0823;SAMARITAN VOWEL SIGN A;Mn;230;NSM;;;;;N;;;;;
+0824;SAMARITAN MODIFIER LETTER SHORT A;Lm;0;R;;;;;N;;;;;
+0825;SAMARITAN VOWEL SIGN SHORT A;Mn;230;NSM;;;;;N;;;;;
+0826;SAMARITAN VOWEL SIGN LONG U;Mn;230;NSM;;;;;N;;;;;
+0827;SAMARITAN VOWEL SIGN U;Mn;230;NSM;;;;;N;;;;;
+0828;SAMARITAN MODIFIER LETTER I;Lm;0;R;;;;;N;;;;;
+0829;SAMARITAN VOWEL SIGN LONG I;Mn;230;NSM;;;;;N;;;;;
+082A;SAMARITAN VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;;
+082B;SAMARITAN VOWEL SIGN O;Mn;230;NSM;;;;;N;;;;;
+082C;SAMARITAN VOWEL SIGN SUKUN;Mn;230;NSM;;;;;N;;;;;
+082D;SAMARITAN MARK NEQUDAA;Mn;230;NSM;;;;;N;;;;;
+0830;SAMARITAN PUNCTUATION NEQUDAA;Po;0;R;;;;;N;;;;;
+0831;SAMARITAN PUNCTUATION AFSAAQ;Po;0;R;;;;;N;;;;;
+0832;SAMARITAN PUNCTUATION ANGED;Po;0;R;;;;;N;;;;;
+0833;SAMARITAN PUNCTUATION BAU;Po;0;R;;;;;N;;;;;
+0834;SAMARITAN PUNCTUATION ATMAAU;Po;0;R;;;;;N;;;;;
+0835;SAMARITAN PUNCTUATION SHIYYAALAA;Po;0;R;;;;;N;;;;;
+0836;SAMARITAN ABBREVIATION MARK;Po;0;R;;;;;N;;;;;
+0837;SAMARITAN PUNCTUATION MELODIC QITSA;Po;0;R;;;;;N;;;;;
+0838;SAMARITAN PUNCTUATION ZIQAA;Po;0;R;;;;;N;;;;;
+0839;SAMARITAN PUNCTUATION QITSA;Po;0;R;;;;;N;;;;;
+083A;SAMARITAN PUNCTUATION ZAEF;Po;0;R;;;;;N;;;;;
+083B;SAMARITAN PUNCTUATION TURU;Po;0;R;;;;;N;;;;;
+083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;;
+083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;;
+083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;;
+0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0904;DEVANAGARI LETTER SHORT A;Lo;0;L;;;;;N;;;;;
+0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;;
+0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;;
+0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;;
+0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;;
+0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;;
+090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;;
+090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;;
+090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;;
+090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;;
+0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;;
+0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;;
+0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;;
+0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;;
+0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;;
+0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;;
+0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;;
+0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;;
+0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;;
+0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;;
+091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;;
+091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;;
+091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;;
+091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;;
+091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;;
+091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;;
+0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;;
+0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;;
+0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;;
+0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;;
+0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;;
+0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;;
+0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;;
+0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;;
+0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;;
+0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;;
+092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;;
+092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;;
+092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;;
+092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;;
+092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;;
+092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;;
+0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;;
+0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;;
+0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;;
+0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;;
+0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;;
+0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;;
+0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;;
+0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;;
+0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;;
+0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;;
+093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
+093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
+0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;;
+0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;;
+0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;;
+094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;;
+094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;;
+0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;;
+0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;;
+0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;;
+0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;;
+0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;;
+0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;;
+0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;;
+0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;;
+095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;;
+095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;;
+095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;;
+095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;;
+095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;;
+095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;;
+0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;;
+0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;;
+0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
+0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;;
+0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;;
+0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;;
+097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;;
+097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;;
+097C;DEVANAGARI LETTER JJA;Lo;0;L;;;;;N;;;;;
+097D;DEVANAGARI LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;;
+097E;DEVANAGARI LETTER DDDA;Lo;0;L;;;;;N;;;;;
+097F;DEVANAGARI LETTER BBA;Lo;0;L;;;;;N;;;;;
+0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
+0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;;
+0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;;
+0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;;
+0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;;
+0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;;
+098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;;
+098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;;
+0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;;
+0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;;
+0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;;
+0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;;
+0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;;
+0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;;
+0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;;
+0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;;
+099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;;
+099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;;
+099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;;
+099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;;
+099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;;
+099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;;
+09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;;
+09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;;
+09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;;
+09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;;
+09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;;
+09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;;
+09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;;
+09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;;
+09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;;
+09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;;
+09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;;
+09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;;
+09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;;
+09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;;
+09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;;
+09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;;
+09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;;
+09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;;
+09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;;
+09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;;
+09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;;
+09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+09BD;BENGALI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
+09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
+09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;;
+09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;;
+09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+09CE;BENGALI LETTER KHANDA TA;Lo;0;L;;;;;N;;;;;
+09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
+09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;;
+09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;;
+09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;;
+09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;;;;
+09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;;;;
+09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;;
+09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
+09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1/16;N;;;;;
+09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;1/8;N;;;;;
+09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3/16;N;;;;;
+09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;1/4;N;;;;;
+09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;3/4;N;;;;;
+09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;;
+09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;;
+09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;;
+0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;;
+0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;;
+0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;;
+0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;;
+0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;;
+0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;;
+0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;;
+0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;;
+0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;;
+0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;;
+0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;;
+0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;;
+0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;;
+0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;;
+0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;;
+0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;;
+0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;;
+0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;;
+0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;;
+0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;;
+0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;;
+0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;;
+0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;;
+0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;;
+0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;;
+0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;;
+0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;;
+0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;;
+0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;;
+0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;;
+0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;;
+0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;;
+0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;;
+0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;;
+0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;;
+0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;;
+0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;;
+0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;;
+0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;;
+0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;;
+0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;;
+0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;;
+0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;;
+0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;;
+0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;;
+0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;;
+0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;;
+0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
+0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0A51;GURMUKHI SIGN UDAAT;Mn;0;NSM;;;;;N;;;;;
+0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;;
+0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;;
+0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;;
+0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;;
+0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;;
+0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;;
+0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;;
+0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;;
+0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;;
+0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;;
+0A75;GURMUKHI SIGN YAKASH;Mn;0;NSM;;;;;N;;;;;
+0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;;
+0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;;
+0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;;
+0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;;
+0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;;
+0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;;
+0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+0A8C;GUJARATI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;;
+0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;;
+0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;;
+0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;;
+0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;;
+0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;;
+0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;;
+0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;;
+0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;;
+0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;;
+0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;;
+0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;;
+0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;;
+0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;;
+0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;;
+0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;;
+0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;;
+0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;;
+0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;;
+0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;;
+0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;;
+0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;;
+0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;;
+0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;;
+0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;;
+0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;;
+0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;;
+0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;;
+0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;;
+0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;;
+0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;;
+0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;;
+0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;;
+0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;;
+0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;;
+0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;;
+0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;;
+0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;;
+0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;;
+0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;;
+0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
+0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
+0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;;
+0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;;
+0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;;
+0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+0AE1;GUJARATI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+0AE2;GUJARATI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+0AE3;GUJARATI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
+0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
+0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;;
+0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;;
+0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;;
+0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;;
+0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;;
+0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;;
+0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;;
+0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;;
+0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;;
+0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;;
+0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;;
+0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;;
+0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;;
+0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;;
+0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;;
+0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;;
+0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;;
+0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;;
+0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;;
+0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;;
+0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;;
+0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;;
+0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;;
+0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;;
+0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;;
+0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;;
+0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;;
+0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;;
+0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;;
+0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;;
+0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;;
+0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;;
+0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;;
+0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;;
+0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;;
+0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;;
+0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;;
+0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;;
+0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;;
+0B35;ORIYA LETTER VA;Lo;0;L;;;;;N;;;;;
+0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;;
+0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;;
+0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;;
+0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;;
+0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
+0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+0B44;ORIYA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
+0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;;
+0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;;
+0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;;
+0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;;
+0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
+0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;;
+0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;;
+0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;;
+0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+0B62;ORIYA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+0B63;ORIYA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;;
+0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;;
+0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;;
+0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;;
+0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;;
+0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;;
+0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;;
+0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;;
+0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;;
+0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;;
+0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;;
+0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;;
+0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;;
+0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;;
+0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;;
+0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;;
+0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;;
+0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;;
+0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;;
+0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;;
+0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;;
+0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;;
+0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;;
+0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;;
+0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;;
+0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;;
+0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;;
+0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;;
+0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;;
+0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;;
+0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;;
+0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;;
+0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;;
+0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;;
+0BB6;TAMIL LETTER SHA;Lo;0;L;;;;;N;;;;;
+0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;;
+0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;;
+0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;;
+0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
+0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
+0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
+0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;;
+0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;;
+0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;;
+0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0BD0;TAMIL OM;Lo;0;L;;;;;N;;;;;
+0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
+0BE6;TAMIL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;;
+0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;;
+0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;;
+0BF3;TAMIL DAY SIGN;So;0;ON;;;;;N;;;;;
+0BF4;TAMIL MONTH SIGN;So;0;ON;;;;;N;;;;;
+0BF5;TAMIL YEAR SIGN;So;0;ON;;;;;N;;;;;
+0BF6;TAMIL DEBIT SIGN;So;0;ON;;;;;N;;;;;
+0BF7;TAMIL CREDIT SIGN;So;0;ON;;;;;N;;;;;
+0BF8;TAMIL AS ABOVE SIGN;So;0;ON;;;;;N;;;;;
+0BF9;TAMIL RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
+0BFA;TAMIL NUMBER SIGN;So;0;ON;;;;;N;;;;;
+0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;;
+0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
+0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;;
+0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;;
+0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;;
+0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;;
+0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;;
+0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;;
+0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;;
+0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;;
+0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;;
+0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;;
+0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;;
+0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;;
+0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;;
+0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;;
+0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;;
+0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;;
+0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;;
+0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;;
+0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;;
+0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;;
+0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;;
+0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;;
+0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;;
+0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;;
+0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;;
+0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;;
+0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;;
+0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;;
+0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;;
+0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;;
+0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;;
+0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;;
+0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;;
+0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;;
+0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;;
+0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;;
+0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;;
+0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;;
+0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;;
+0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;;
+0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;;
+0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;;
+0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;;
+0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;;
+0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;;
+0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;;
+0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;;
+0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
+0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
+0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
+0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
+0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
+0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
+0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;;
+0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;;
+0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;;
+0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
+0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;;
+0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;;
+0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;;
+0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;;
+0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+0C63;TELUGU VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0C78;TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR;No;0;ON;;;;0;N;;;;;
+0C79;TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR;No;0;ON;;;;1;N;;;;;
+0C7A;TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR;No;0;ON;;;;2;N;;;;;
+0C7B;TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR;No;0;ON;;;;3;N;;;;;
+0C7C;TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR;No;0;ON;;;;1;N;;;;;
+0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;;
+0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;;
+0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;;
+0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
+0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;;
+0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;;
+0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;;
+0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;;
+0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;;
+0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;;
+0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;;
+0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;;
+0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;;
+0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;;
+0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;;
+0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;;
+0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;;
+0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;;
+0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;;
+0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;;
+0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;;
+0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;;
+0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;;
+0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;;
+0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;;
+0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;;
+0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;;
+0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;;
+0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;;
+0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;;
+0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;;
+0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;;
+0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;;
+0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;;
+0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;;
+0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;;
+0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;;
+0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;;
+0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;;
+0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;;
+0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;;
+0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;;
+0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;;
+0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;;
+0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;;
+0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;;
+0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;;
+0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;;
+0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;;
+0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;;
+0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;;
+0CBC;KANNADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+0CBD;KANNADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
+0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+0CBF;KANNADA VOWEL SIGN I;Mn;0;L;;;;;N;;;;;
+0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;;
+0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
+0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
+0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
+0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
+0CC6;KANNADA VOWEL SIGN E;Mn;0;L;;;;;N;;;;;
+0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;;
+0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;;
+0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;;
+0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;;
+0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
+0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;;
+0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;;
+0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;;
+0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+0CE2;KANNADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+0CE3;KANNADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0CF1;KANNADA SIGN JIHVAMULIYA;So;0;ON;;;;;N;;;;;
+0CF2;KANNADA SIGN UPADHMANIYA;So;0;ON;;;;;N;;;;;
+0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
+0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;;
+0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;;
+0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;;
+0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;;
+0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;;
+0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;;
+0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;;
+0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;;
+0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;;
+0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;;
+0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;;
+0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;;
+0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;;
+0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;;
+0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;;
+0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;;
+0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;;
+0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;;
+0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;;
+0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;;
+0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;;
+0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;;
+0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;;
+0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;;
+0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;;
+0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;;
+0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;;
+0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;;
+0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;;
+0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;;
+0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;;
+0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;;
+0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;;
+0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;;
+0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;;
+0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;;
+0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;;
+0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;;
+0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;;
+0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;;
+0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;;
+0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;;
+0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;;
+0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;;
+0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;;
+0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;;
+0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;;
+0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;;
+0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
+0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+0D44;MALAYALAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;;
+0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
+0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
+0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;;
+0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;;
+0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
+0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+0D63;MALAYALAM VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0D70;MALAYALAM NUMBER TEN;No;0;L;;;;10;N;;;;;
+0D71;MALAYALAM NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;;
+0D72;MALAYALAM NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;;
+0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;;
+0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;;
+0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;;
+0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;;
+0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;;
+0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;;
+0D7C;MALAYALAM LETTER CHILLU RR;Lo;0;L;;;;;N;;;;;
+0D7D;MALAYALAM LETTER CHILLU L;Lo;0;L;;;;;N;;;;;
+0D7E;MALAYALAM LETTER CHILLU LL;Lo;0;L;;;;;N;;;;;
+0D7F;MALAYALAM LETTER CHILLU K;Lo;0;L;;;;;N;;;;;
+0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;;
+0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;;
+0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;;
+0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;;
+0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;;
+0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;;
+0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;;
+0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;;
+0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;;
+0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;;
+0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;;
+0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;;
+0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;;
+0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;;
+0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;;
+0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;;
+0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;;
+0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;;
+0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;;
+0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;;
+0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;;
+0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;;
+0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;;
+0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;;
+0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;;
+0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;;
+0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;;
+0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;;
+0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;;
+0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;;
+0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;;
+0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;;
+0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;;
+0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;;
+0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;;
+0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;;
+0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;;
+0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;;
+0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;;
+0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;;
+0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;;
+0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;;
+0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;;
+0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;;
+0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;;
+0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;;
+0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;;
+0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;;
+0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;;
+0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;;
+0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;;
+0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;;
+0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;;
+0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;;
+0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;;
+0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;;
+0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;;
+0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;;
+0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;;
+0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;;
+0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;;
+0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;;
+0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;;
+0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;;
+0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;;
+0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;;
+0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;;
+0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;;
+0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;;
+0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;;
+0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;;
+0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;;
+0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;;
+0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;;
+0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;;
+0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;;
+0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;;
+0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;;
+0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;;
+0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;;
+0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;;
+0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;;
+0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;;
+0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;;
+0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;;
+0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;;
+0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;;
+0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;;
+0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;;
+0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;;
+0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;;
+0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;;
+0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;;
+0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;;
+0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;;
+0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;;
+0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;;
+0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;;
+0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;;
+0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;;
+0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;;
+0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;;
+0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;;
+0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;;
+0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;;
+0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;;
+0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;;
+0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;;
+0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;;
+0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;;
+0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;;
+0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;;
+0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;;
+0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;;
+0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;;
+0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;;
+0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;;
+0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;;
+0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;;
+0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;;
+0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;;
+0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;;
+0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;;
+0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;;
+0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;;
+0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;;
+0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;;;;
+0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;;
+0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;;
+0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;;
+0E33;THAI CHARACTER SARA AM;Lo;0;L;<compat> 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;;
+0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;;
+0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;;
+0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;;
+0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;;;;
+0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;;
+0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;;
+0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;;
+0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;;
+0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;;
+0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;;
+0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;;
+0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;;;;
+0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;;;;
+0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;;;;
+0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;;;;
+0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;;;;
+0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;;
+0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;;
+0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;;
+0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;;
+0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;;
+0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;;;;
+0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;;
+0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;;
+0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;;
+0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;;
+0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;;
+0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;;
+0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;;
+0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;;
+0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;;
+0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;;
+0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;;
+0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;;
+0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;;
+0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;;
+0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;;
+0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;;
+0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;;
+0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;;
+0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;;
+0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;;
+0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;;
+0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;;
+0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;;
+0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;;
+0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;;
+0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;;
+0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;;
+0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;;
+0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;;
+0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;;
+0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;;
+0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;;
+0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;;
+0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;;
+0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;;
+0EB3;LAO VOWEL SIGN AM;Lo;0;L;<compat> 0ECD 0EB2;;;;N;;;;;
+0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;;
+0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;;
+0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;;
+0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;;
+0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;;
+0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;;
+0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;;
+0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;;
+0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;;
+0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;;
+0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;;
+0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;;
+0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;;
+0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;;
+0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;;
+0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;;
+0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;;
+0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;;
+0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;;
+0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0EDC;LAO HO NO;Lo;0;L;<compat> 0EAB 0E99;;;;N;;;;;
+0EDD;LAO HO MO;Lo;0;L;<compat> 0EAB 0EA1;;;;N;;;;;
+0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;;
+0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;;;;
+0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;;;;
+0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;;;;
+0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;;;;
+0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;;
+0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;;;;
+0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;;;;
+0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;;;;
+0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;;;;
+0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;;;;
+0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;;;;
+0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L;<noBreak> 0F0B;;;;N;;;;;
+0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;;;;
+0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;;;;
+0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;;;;
+0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;;;;
+0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;;;;
+0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;;;;
+0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;;;;
+0F14;TIBETAN MARK GTER TSHEG;So;0;L;;;;;N;TIBETAN COMMA;;;;
+0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;;;;
+0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;;;;
+0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;;;;
+0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;;;;
+0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;;;;
+0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;;;;
+0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;;;;
+0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;;;;
+0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;;;;
+0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;;;;
+0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;;;;
+0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;;
+0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;;
+0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;;
+0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;;
+0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;;
+0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;;
+0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;;
+0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;;
+0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;;
+0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;;
+0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;;;;
+0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;;;;
+0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;;;;
+0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;;;;
+0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;;;;
+0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;;;;
+0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;Y;;;;;
+0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;Y;;;;;
+0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;Y;TIBETAN LEFT BRACE;;;;
+0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;Y;TIBETAN RIGHT BRACE;;;;
+0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;;;;
+0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;;;;
+0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;;
+0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;;
+0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;;
+0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;;
+0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;;
+0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;;
+0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;;
+0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;;
+0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;;
+0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;;
+0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;;
+0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;;
+0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;;
+0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;;
+0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;;
+0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;;
+0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;;
+0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;;
+0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;;
+0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;;
+0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;;
+0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;;
+0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;;
+0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;;
+0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;;
+0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;;
+0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;;
+0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;;
+0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;;
+0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;;
+0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;;
+0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;;
+0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;;
+0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;;;;
+0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;;
+0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;;
+0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;;
+0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;;
+0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;;
+0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;;
+0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;;
+0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;;;;
+0F6B;TIBETAN LETTER KKA;Lo;0;L;;;;;N;;;;;
+0F6C;TIBETAN LETTER RRA;Lo;0;L;;;;;N;;;;;
+0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;;
+0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;;
+0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;;
+0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;;
+0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;;
+0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;;
+0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM;<compat> 0FB2 0F81;;;;N;;;;;
+0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;;
+0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM;<compat> 0FB3 0F81;;;;N;;;;;
+0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;;
+0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;;
+0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;;
+0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;;
+0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;;;;
+0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;;;;
+0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;;
+0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;;
+0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;;;;
+0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;;;;
+0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;;
+0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;;
+0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;;;;
+0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;;;;
+0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;;;;
+0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;;
+0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;;
+0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;;
+0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;;
+0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;;
+0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;;
+0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;;
+0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;;
+0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;;
+0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;;
+0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;;
+0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;;
+0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;;
+0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;;
+0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;;
+0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;;
+0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;;
+0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;;
+0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;;
+0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;;
+0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;;
+0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;;
+0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;;
+0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;;
+0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;;
+0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;;
+0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;;
+0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;;
+0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;;
+0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;;
+0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;;
+0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;;
+0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;;
+0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;;
+0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;;
+0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;;;;
+0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;;
+0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;;
+0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;;
+0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;;
+0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;;
+0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;;
+0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;;
+0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;;
+0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;;;;
+0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;;;;
+0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;;;;
+0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;;;;
+0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;;;;
+0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;;
+0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;;
+0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;;;;
+0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;;;;
+0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;;;;
+0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;;;;
+0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;;;;
+0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;;;;
+0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;;;;
+0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;;;;
+0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;;;;
+0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;;;;
+0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;;;;
+0FCE;TIBETAN SIGN RDEL NAG RDEL DKAR;So;0;L;;;;;N;;;;;
+0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;;;;
+0FD0;TIBETAN MARK BSKA- SHOG GI MGO RGYAN;Po;0;L;;;;;N;;;;;
+0FD1;TIBETAN MARK MNYAM YIG GI MGO RGYAN;Po;0;L;;;;;N;;;;;
+0FD2;TIBETAN MARK NYIS TSHEG;Po;0;L;;;;;N;;;;;
+0FD3;TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA;Po;0;L;;;;;N;;;;;
+0FD4;TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;;
+0FD5;RIGHT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;;
+0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;;
+0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;;
+0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;;
+1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;;
+1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;;
+1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;;
+1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;;
+1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;;
+1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;;
+1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;;
+1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;;
+1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;;
+1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;;
+100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;;
+100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;;
+100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;;
+100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;;
+100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;;
+100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;;
+1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;;
+1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;;
+1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;;
+1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;;
+1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;;
+1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;;
+1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;;
+1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;;
+1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;;
+1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;;
+101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;;
+101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;;
+101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;;
+101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;;
+101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;;
+101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;;
+1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;;
+1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;;
+1022;MYANMAR LETTER SHAN A;Lo;0;L;;;;;N;;;;;
+1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;;
+1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;;
+1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;;
+1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;;
+1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;;
+1028;MYANMAR LETTER MON E;Lo;0;L;;;;;N;;;;;
+1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;;
+102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;;
+102B;MYANMAR VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;;
+102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+1033;MYANMAR VOWEL SIGN MON II;Mn;0;NSM;;;;;N;;;;;
+1034;MYANMAR VOWEL SIGN MON O;Mn;0;NSM;;;;;N;;;;;
+1035;MYANMAR VOWEL SIGN E ABOVE;Mn;0;NSM;;;;;N;;;;;
+1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;;
+1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+103A;MYANMAR SIGN ASAT;Mn;9;NSM;;;;;N;;;;;
+103B;MYANMAR CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;;
+103C;MYANMAR CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;;
+103D;MYANMAR CONSONANT SIGN MEDIAL WA;Mn;0;NSM;;;;;N;;;;;
+103E;MYANMAR CONSONANT SIGN MEDIAL HA;Mn;0;NSM;;;;;N;;;;;
+103F;MYANMAR LETTER GREAT SA;Lo;0;L;;;;;N;;;;;
+1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;;
+104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;;
+104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;;
+104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;;
+104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;;
+104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;;
+1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;;
+1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;;
+1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
+1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
+1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;;
+105A;MYANMAR LETTER MON NGA;Lo;0;L;;;;;N;;;;;
+105B;MYANMAR LETTER MON JHA;Lo;0;L;;;;;N;;;;;
+105C;MYANMAR LETTER MON BBA;Lo;0;L;;;;;N;;;;;
+105D;MYANMAR LETTER MON BBE;Lo;0;L;;;;;N;;;;;
+105E;MYANMAR CONSONANT SIGN MON MEDIAL NA;Mn;0;NSM;;;;;N;;;;;
+105F;MYANMAR CONSONANT SIGN MON MEDIAL MA;Mn;0;NSM;;;;;N;;;;;
+1060;MYANMAR CONSONANT SIGN MON MEDIAL LA;Mn;0;NSM;;;;;N;;;;;
+1061;MYANMAR LETTER SGAW KAREN SHA;Lo;0;L;;;;;N;;;;;
+1062;MYANMAR VOWEL SIGN SGAW KAREN EU;Mc;0;L;;;;;N;;;;;
+1063;MYANMAR TONE MARK SGAW KAREN HATHI;Mc;0;L;;;;;N;;;;;
+1064;MYANMAR TONE MARK SGAW KAREN KE PHO;Mc;0;L;;;;;N;;;;;
+1065;MYANMAR LETTER WESTERN PWO KAREN THA;Lo;0;L;;;;;N;;;;;
+1066;MYANMAR LETTER WESTERN PWO KAREN PWA;Lo;0;L;;;;;N;;;;;
+1067;MYANMAR VOWEL SIGN WESTERN PWO KAREN EU;Mc;0;L;;;;;N;;;;;
+1068;MYANMAR VOWEL SIGN WESTERN PWO KAREN UE;Mc;0;L;;;;;N;;;;;
+1069;MYANMAR SIGN WESTERN PWO KAREN TONE-1;Mc;0;L;;;;;N;;;;;
+106A;MYANMAR SIGN WESTERN PWO KAREN TONE-2;Mc;0;L;;;;;N;;;;;
+106B;MYANMAR SIGN WESTERN PWO KAREN TONE-3;Mc;0;L;;;;;N;;;;;
+106C;MYANMAR SIGN WESTERN PWO KAREN TONE-4;Mc;0;L;;;;;N;;;;;
+106D;MYANMAR SIGN WESTERN PWO KAREN TONE-5;Mc;0;L;;;;;N;;;;;
+106E;MYANMAR LETTER EASTERN PWO KAREN NNA;Lo;0;L;;;;;N;;;;;
+106F;MYANMAR LETTER EASTERN PWO KAREN YWA;Lo;0;L;;;;;N;;;;;
+1070;MYANMAR LETTER EASTERN PWO KAREN GHWA;Lo;0;L;;;;;N;;;;;
+1071;MYANMAR VOWEL SIGN GEBA KAREN I;Mn;0;NSM;;;;;N;;;;;
+1072;MYANMAR VOWEL SIGN KAYAH OE;Mn;0;NSM;;;;;N;;;;;
+1073;MYANMAR VOWEL SIGN KAYAH U;Mn;0;NSM;;;;;N;;;;;
+1074;MYANMAR VOWEL SIGN KAYAH EE;Mn;0;NSM;;;;;N;;;;;
+1075;MYANMAR LETTER SHAN KA;Lo;0;L;;;;;N;;;;;
+1076;MYANMAR LETTER SHAN KHA;Lo;0;L;;;;;N;;;;;
+1077;MYANMAR LETTER SHAN GA;Lo;0;L;;;;;N;;;;;
+1078;MYANMAR LETTER SHAN CA;Lo;0;L;;;;;N;;;;;
+1079;MYANMAR LETTER SHAN ZA;Lo;0;L;;;;;N;;;;;
+107A;MYANMAR LETTER SHAN NYA;Lo;0;L;;;;;N;;;;;
+107B;MYANMAR LETTER SHAN DA;Lo;0;L;;;;;N;;;;;
+107C;MYANMAR LETTER SHAN NA;Lo;0;L;;;;;N;;;;;
+107D;MYANMAR LETTER SHAN PHA;Lo;0;L;;;;;N;;;;;
+107E;MYANMAR LETTER SHAN FA;Lo;0;L;;;;;N;;;;;
+107F;MYANMAR LETTER SHAN BA;Lo;0;L;;;;;N;;;;;
+1080;MYANMAR LETTER SHAN THA;Lo;0;L;;;;;N;;;;;
+1081;MYANMAR LETTER SHAN HA;Lo;0;L;;;;;N;;;;;
+1082;MYANMAR CONSONANT SIGN SHAN MEDIAL WA;Mn;0;NSM;;;;;N;;;;;
+1083;MYANMAR VOWEL SIGN SHAN AA;Mc;0;L;;;;;N;;;;;
+1084;MYANMAR VOWEL SIGN SHAN E;Mc;0;L;;;;;N;;;;;
+1085;MYANMAR VOWEL SIGN SHAN E ABOVE;Mn;0;NSM;;;;;N;;;;;
+1086;MYANMAR VOWEL SIGN SHAN FINAL Y;Mn;0;NSM;;;;;N;;;;;
+1087;MYANMAR SIGN SHAN TONE-2;Mc;0;L;;;;;N;;;;;
+1088;MYANMAR SIGN SHAN TONE-3;Mc;0;L;;;;;N;;;;;
+1089;MYANMAR SIGN SHAN TONE-5;Mc;0;L;;;;;N;;;;;
+108A;MYANMAR SIGN SHAN TONE-6;Mc;0;L;;;;;N;;;;;
+108B;MYANMAR SIGN SHAN COUNCIL TONE-2;Mc;0;L;;;;;N;;;;;
+108C;MYANMAR SIGN SHAN COUNCIL TONE-3;Mc;0;L;;;;;N;;;;;
+108D;MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE;Mn;220;NSM;;;;;N;;;;;
+108E;MYANMAR LETTER RUMAI PALAUNG FA;Lo;0;L;;;;;N;;;;;
+108F;MYANMAR SIGN RUMAI PALAUNG TONE-5;Mc;0;L;;;;;N;;;;;
+1090;MYANMAR SHAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1091;MYANMAR SHAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1092;MYANMAR SHAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1093;MYANMAR SHAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1094;MYANMAR SHAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1095;MYANMAR SHAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1096;MYANMAR SHAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1097;MYANMAR SHAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1098;MYANMAR SHAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1099;MYANMAR SHAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+109A;MYANMAR SIGN KHAMTI TONE-1;Mc;0;L;;;;;N;;;;;
+109B;MYANMAR SIGN KHAMTI TONE-3;Mc;0;L;;;;;N;;;;;
+109C;MYANMAR VOWEL SIGN AITON A;Mc;0;L;;;;;N;;;;;
+109D;MYANMAR VOWEL SIGN AITON AI;Mn;0;NSM;;;;;N;;;;;
+109E;MYANMAR SYMBOL SHAN ONE;So;0;L;;;;;N;;;;;
+109F;MYANMAR SYMBOL SHAN EXCLAMATION;So;0;L;;;;;N;;;;;
+10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;2D00;
+10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;2D01;
+10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;2D02;
+10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;2D03;
+10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;2D04;
+10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;2D05;
+10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;2D06;
+10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;2D07;
+10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;2D08;
+10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;2D09;
+10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;2D0A;
+10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;2D0B;
+10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;2D0C;
+10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;2D0D;
+10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;2D0E;
+10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;2D0F;
+10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;2D10;
+10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;2D11;
+10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;2D12;
+10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;2D13;
+10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;2D14;
+10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;2D15;
+10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;2D16;
+10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;2D17;
+10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;2D18;
+10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;2D19;
+10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;2D1A;
+10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;2D1B;
+10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;2D1C;
+10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;2D1D;
+10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;2D1E;
+10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;2D1F;
+10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;2D20;
+10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;2D21;
+10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;2D22;
+10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;2D23;
+10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;2D24;
+10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;2D25;
+10D0;GEORGIAN LETTER AN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;;;
+10D1;GEORGIAN LETTER BAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;;;
+10D2;GEORGIAN LETTER GAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;;;
+10D3;GEORGIAN LETTER DON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;;;
+10D4;GEORGIAN LETTER EN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;;;
+10D5;GEORGIAN LETTER VIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;;;
+10D6;GEORGIAN LETTER ZEN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;;;
+10D7;GEORGIAN LETTER TAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;;;
+10D8;GEORGIAN LETTER IN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;;;
+10D9;GEORGIAN LETTER KAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;;;
+10DA;GEORGIAN LETTER LAS;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;;;
+10DB;GEORGIAN LETTER MAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;;;
+10DC;GEORGIAN LETTER NAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;;;
+10DD;GEORGIAN LETTER ON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;;;
+10DE;GEORGIAN LETTER PAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;;;
+10DF;GEORGIAN LETTER ZHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;;;
+10E0;GEORGIAN LETTER RAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;;;
+10E1;GEORGIAN LETTER SAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;;;
+10E2;GEORGIAN LETTER TAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;;;
+10E3;GEORGIAN LETTER UN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;;;
+10E4;GEORGIAN LETTER PHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;;;
+10E5;GEORGIAN LETTER KHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;;;
+10E6;GEORGIAN LETTER GHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;;;
+10E7;GEORGIAN LETTER QAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;;;
+10E8;GEORGIAN LETTER SHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;;;
+10E9;GEORGIAN LETTER CHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;;;
+10EA;GEORGIAN LETTER CAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;;;
+10EB;GEORGIAN LETTER JIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;;;
+10EC;GEORGIAN LETTER CIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;;;
+10ED;GEORGIAN LETTER CHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;;;
+10EE;GEORGIAN LETTER XAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;;;
+10EF;GEORGIAN LETTER JHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;;;
+10F0;GEORGIAN LETTER HAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;;;
+10F1;GEORGIAN LETTER HE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;;;
+10F2;GEORGIAN LETTER HIE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;;;
+10F3;GEORGIAN LETTER WE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;;;
+10F4;GEORGIAN LETTER HAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;;;
+10F5;GEORGIAN LETTER HOE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;;;
+10F6;GEORGIAN LETTER FI;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;;;
+10F7;GEORGIAN LETTER YN;Lo;0;L;;;;;N;;;;;
+10F8;GEORGIAN LETTER ELIFI;Lo;0;L;;;;;N;;;;;
+10F9;GEORGIAN LETTER TURNED GAN;Lo;0;L;;;;;N;;;;;
+10FA;GEORGIAN LETTER AIN;Lo;0;L;;;;;N;;;;;
+10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;;
+10FC;MODIFIER LETTER GEORGIAN NAR;Lm;0;L;<super> 10DC;;;;N;;;;;
+1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;;
+1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
+1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;;;;
+1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;;;;
+1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;;
+1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;;;;
+1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;;;;
+1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;;;;
+1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;;
+1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;;;;
+110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;;
+110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;;
+110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;;;;
+110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;;
+110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;;;;
+110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;;;;
+1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;;;;
+1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;;;;
+1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;;;;
+1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;;
+1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;;
+1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;;
+1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;;
+1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;;
+1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;;
+1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;;
+111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;;
+111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;;
+111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;;
+111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;;
+111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;;
+111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;;
+1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;;
+1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
+1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
+1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
+1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;;
+1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;;
+1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;;
+1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;;
+1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;;
+1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;;
+112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;;
+112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
+112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;;
+112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
+112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;;
+112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
+1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;;
+1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;;
+1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;;
+1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;;
+1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;;
+1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;;
+1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;;
+1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;;
+1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;;
+1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;;
+113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;;
+113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;;
+113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;;
+113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;;
+113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;;
+113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;;
+1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;;
+1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;;
+1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;;
+1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;;
+1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;;
+1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;;
+1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;;
+1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;;
+1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;;
+1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;;
+114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;;
+114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;;
+114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;;
+114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;;
+114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;;
+114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;;
+1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;;
+1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;;
+1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;;
+1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;;
+1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;;
+1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;;
+1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;;
+1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;;
+1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;;
+1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;;
+115A;HANGUL CHOSEONG KIYEOK-TIKEUT;Lo;0;L;;;;;N;;;;;
+115B;HANGUL CHOSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;;
+115C;HANGUL CHOSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;;
+115D;HANGUL CHOSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;;
+115E;HANGUL CHOSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;;
+115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;;
+1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;;
+1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;;
+1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;;
+1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;;
+1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;;
+1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;;
+1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;;
+1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;;
+1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;;
+1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;;
+116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;;
+116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;;
+116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;;
+116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;;
+116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;;
+116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;;
+1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;;
+1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;;
+1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;;
+1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;;
+1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;;
+1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;;
+1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;;
+1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;;
+1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;;
+1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;;
+117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;;
+117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;;
+117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;;
+117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;;
+117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;;
+117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;;
+1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;;
+1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;;
+1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;;
+1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;;
+1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;;
+1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;;
+1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;;
+1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;;
+1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;;
+1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;;
+118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;;
+118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;;
+118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;;
+118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;;
+118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;;
+118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;;
+1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;;
+1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;;
+1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;;
+1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;;
+1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;;
+1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;;
+1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;;
+1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;;
+1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;;
+1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;;
+119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;;
+119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;;
+119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;;
+119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;;
+119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;;
+119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;;
+11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;;
+11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;;
+11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;;
+11A3;HANGUL JUNGSEONG A-EU;Lo;0;L;;;;;N;;;;;
+11A4;HANGUL JUNGSEONG YA-U;Lo;0;L;;;;;N;;;;;
+11A5;HANGUL JUNGSEONG YEO-YA;Lo;0;L;;;;;N;;;;;
+11A6;HANGUL JUNGSEONG O-YA;Lo;0;L;;;;;N;;;;;
+11A7;HANGUL JUNGSEONG O-YAE;Lo;0;L;;;;;N;;;;;
+11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;;;;
+11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
+11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;;;;
+11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;;;;
+11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;;
+11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;;
+11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;;;;
+11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;;;;
+11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;;
+11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;;
+11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;;
+11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;;
+11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;;;;
+11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;;
+11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;;
+11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;;;;
+11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;;;;
+11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
+11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;;;;
+11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;;
+11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;;;;
+11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;;;;
+11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;;;;
+11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;;;;
+11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;;;;
+11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;;;;
+11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;;;;
+11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;;
+11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
+11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;;
+11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;;
+11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;;
+11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;;
+11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;;
+11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;;
+11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;;
+11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;;
+11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;;
+11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;;
+11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;;
+11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;;
+11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;;
+11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;;
+11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
+11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;;
+11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
+11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;;
+11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;;
+11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;;
+11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;;
+11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;;
+11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;;
+11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;;
+11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;;
+11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;;
+11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;;
+11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;;
+11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;;
+11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;;
+11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;;
+11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;;
+11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;;
+11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
+11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
+11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
+11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;;
+11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;;
+11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;;
+11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;;
+11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
+11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;;
+11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;;
+11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;;
+11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;;
+11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;;
+11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;;
+11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;;
+11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;;
+11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;;
+11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;;
+11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;;
+11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;;
+11FA;HANGUL JONGSEONG KIYEOK-NIEUN;Lo;0;L;;;;;N;;;;;
+11FB;HANGUL JONGSEONG KIYEOK-PIEUP;Lo;0;L;;;;;N;;;;;
+11FC;HANGUL JONGSEONG KIYEOK-CHIEUCH;Lo;0;L;;;;;N;;;;;
+11FD;HANGUL JONGSEONG KIYEOK-KHIEUKH;Lo;0;L;;;;;N;;;;;
+11FE;HANGUL JONGSEONG KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;;
+11FF;HANGUL JONGSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;;
+1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;;
+1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;;
+1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;;
+1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;;
+1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;;
+1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;;
+1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;;
+1207;ETHIOPIC SYLLABLE HOA;Lo;0;L;;;;;N;;;;;
+1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;;
+1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;;
+120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;;
+120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;;
+120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;;
+120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;;
+120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;;
+120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;;
+1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;;
+1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;;
+1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;;
+1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;;
+1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;;
+1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;;
+1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;;
+1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;;
+1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;;
+1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;;
+121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;;
+121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;;
+121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;;
+121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;;
+121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;;
+121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;;
+1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;;
+1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;;
+1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;;
+1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;;
+1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;;
+1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;;
+1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;;
+1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;;
+1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;;
+1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;;
+122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;;
+122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;;
+122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;;
+122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;;
+122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;;
+122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;;
+1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;;
+1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;;
+1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;;
+1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;;
+1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;;
+1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;;
+1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;;
+1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;;
+1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;;
+1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;;
+123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;;
+123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;;
+123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;;
+123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;;
+123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;;
+123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;;
+1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;;
+1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;;
+1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;;
+1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;;
+1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;;
+1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;;
+1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;;
+1247;ETHIOPIC SYLLABLE QOA;Lo;0;L;;;;;N;;;;;
+1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;;
+124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;;
+124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;;
+124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;;
+124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;;
+1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;;
+1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;;
+1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;;
+1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;;
+1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;;
+1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;;
+1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;;
+1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;;
+125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;;
+125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;;
+125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;;
+125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;;
+1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;;
+1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;;
+1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;;
+1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;;
+1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;;
+1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;;
+1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;;
+1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;;
+1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;;
+1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;;
+126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;;
+126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;;
+126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;;
+126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;;
+126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;;
+126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;;
+1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;;
+1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;;
+1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;;
+1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;;
+1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;;
+1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;;
+1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;;
+1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;;
+1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;;
+1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;;
+127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;;
+127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;;
+127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;;
+127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;;
+127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;;
+127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;;
+1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;;
+1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;;
+1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;;
+1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;;
+1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;;
+1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;;
+1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;;
+1287;ETHIOPIC SYLLABLE XOA;Lo;0;L;;;;;N;;;;;
+1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;;
+128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;;
+128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;;
+128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;;
+128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;;
+1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;;
+1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;;
+1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;;
+1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;;
+1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;;
+1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;;
+1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;;
+1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;;
+1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;;
+1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;;
+129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;;
+129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;;
+129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;;
+129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;;
+129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;;
+129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;;
+12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;;
+12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;;
+12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;;
+12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;;
+12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;;
+12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;;
+12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;;
+12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;;
+12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;;
+12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;;
+12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;;
+12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;;
+12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;;
+12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;;
+12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;;
+12AF;ETHIOPIC SYLLABLE KOA;Lo;0;L;;;;;N;;;;;
+12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;;
+12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;;
+12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;;
+12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;;
+12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;;
+12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;;
+12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;;
+12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;;
+12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;;
+12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;;
+12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;;
+12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;;
+12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;;
+12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;;
+12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;;
+12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;;
+12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;;
+12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;;
+12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;;
+12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;;
+12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;;
+12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;;
+12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;;
+12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;;
+12CF;ETHIOPIC SYLLABLE WOA;Lo;0;L;;;;;N;;;;;
+12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;;
+12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;;
+12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;;
+12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;;
+12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;;
+12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;;
+12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;;
+12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;;
+12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;;
+12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;;
+12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;;
+12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;;
+12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;;
+12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;;
+12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;;
+12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;;
+12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;;
+12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;;
+12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;;
+12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;;
+12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;;
+12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;;
+12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;;
+12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;;
+12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;;
+12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;;
+12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;;
+12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;;
+12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;;
+12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;;
+12EF;ETHIOPIC SYLLABLE YOA;Lo;0;L;;;;;N;;;;;
+12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;;
+12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;;
+12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;;
+12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;;
+12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;;
+12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;;
+12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;;
+12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;;
+12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;;
+12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;;
+12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;;
+12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;;
+12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;;
+12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;;
+12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;;
+12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;;
+1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;;
+1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;;
+1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;;
+1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;;
+1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;;
+1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;;
+1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;;
+1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;;
+1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;;
+1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;;
+130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;;
+130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;;
+130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;;
+130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;;
+130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;;
+130F;ETHIOPIC SYLLABLE GOA;Lo;0;L;;;;;N;;;;;
+1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;;
+1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;;
+1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;;
+1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;;
+1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;;
+1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;;
+1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;;
+131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;;
+131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;;
+131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;;
+131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;;
+131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;;
+131F;ETHIOPIC SYLLABLE GGWAA;Lo;0;L;;;;;N;;;;;
+1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;;
+1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;;
+1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;;
+1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;;
+1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;;
+1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;;
+1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;;
+1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;;
+1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;;
+1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;;
+132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;;
+132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;;
+132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;;
+132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;;
+132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;;
+132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;;
+1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;;
+1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;;
+1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;;
+1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;;
+1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;;
+1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;;
+1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;;
+1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;;
+1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;;
+1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;;
+133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;;
+133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;;
+133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;;
+133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;;
+133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;;
+133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;;
+1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;;
+1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;;
+1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;;
+1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;;
+1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;;
+1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;;
+1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;;
+1347;ETHIOPIC SYLLABLE TZOA;Lo;0;L;;;;;N;;;;;
+1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;;
+1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;;
+134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;;
+134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;;
+134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;;
+134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;;
+134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;;
+134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;;
+1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;;
+1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;;
+1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;;
+1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;;
+1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;;
+1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;;
+1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;;
+1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;;
+1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;;
+1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;;
+135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;;
+135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;;
+1360;ETHIOPIC SECTION MARK;So;0;L;;;;;N;;;;;
+1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;;
+1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;;
+1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;;
+1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;;
+1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;;
+1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;;
+1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;;
+1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;;
+1369;ETHIOPIC DIGIT ONE;No;0;L;;;1;1;N;;;;;
+136A;ETHIOPIC DIGIT TWO;No;0;L;;;2;2;N;;;;;
+136B;ETHIOPIC DIGIT THREE;No;0;L;;;3;3;N;;;;;
+136C;ETHIOPIC DIGIT FOUR;No;0;L;;;4;4;N;;;;;
+136D;ETHIOPIC DIGIT FIVE;No;0;L;;;5;5;N;;;;;
+136E;ETHIOPIC DIGIT SIX;No;0;L;;;6;6;N;;;;;
+136F;ETHIOPIC DIGIT SEVEN;No;0;L;;;7;7;N;;;;;
+1370;ETHIOPIC DIGIT EIGHT;No;0;L;;;8;8;N;;;;;
+1371;ETHIOPIC DIGIT NINE;No;0;L;;;9;9;N;;;;;
+1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;;
+1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;;
+1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;;
+1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;;
+1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;;
+1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;;
+1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;;
+1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;;
+137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;;
+137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;;
+137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;;
+1380;ETHIOPIC SYLLABLE SEBATBEIT MWA;Lo;0;L;;;;;N;;;;;
+1381;ETHIOPIC SYLLABLE MWI;Lo;0;L;;;;;N;;;;;
+1382;ETHIOPIC SYLLABLE MWEE;Lo;0;L;;;;;N;;;;;
+1383;ETHIOPIC SYLLABLE MWE;Lo;0;L;;;;;N;;;;;
+1384;ETHIOPIC SYLLABLE SEBATBEIT BWA;Lo;0;L;;;;;N;;;;;
+1385;ETHIOPIC SYLLABLE BWI;Lo;0;L;;;;;N;;;;;
+1386;ETHIOPIC SYLLABLE BWEE;Lo;0;L;;;;;N;;;;;
+1387;ETHIOPIC SYLLABLE BWE;Lo;0;L;;;;;N;;;;;
+1388;ETHIOPIC SYLLABLE SEBATBEIT FWA;Lo;0;L;;;;;N;;;;;
+1389;ETHIOPIC SYLLABLE FWI;Lo;0;L;;;;;N;;;;;
+138A;ETHIOPIC SYLLABLE FWEE;Lo;0;L;;;;;N;;;;;
+138B;ETHIOPIC SYLLABLE FWE;Lo;0;L;;;;;N;;;;;
+138C;ETHIOPIC SYLLABLE SEBATBEIT PWA;Lo;0;L;;;;;N;;;;;
+138D;ETHIOPIC SYLLABLE PWI;Lo;0;L;;;;;N;;;;;
+138E;ETHIOPIC SYLLABLE PWEE;Lo;0;L;;;;;N;;;;;
+138F;ETHIOPIC SYLLABLE PWE;Lo;0;L;;;;;N;;;;;
+1390;ETHIOPIC TONAL MARK YIZET;So;0;ON;;;;;N;;;;;
+1391;ETHIOPIC TONAL MARK DERET;So;0;ON;;;;;N;;;;;
+1392;ETHIOPIC TONAL MARK RIKRIK;So;0;ON;;;;;N;;;;;
+1393;ETHIOPIC TONAL MARK SHORT RIKRIK;So;0;ON;;;;;N;;;;;
+1394;ETHIOPIC TONAL MARK DIFAT;So;0;ON;;;;;N;;;;;
+1395;ETHIOPIC TONAL MARK KENAT;So;0;ON;;;;;N;;;;;
+1396;ETHIOPIC TONAL MARK CHIRET;So;0;ON;;;;;N;;;;;
+1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;;
+1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;;
+1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;;
+13A0;CHEROKEE LETTER A;Lo;0;L;;;;;N;;;;;
+13A1;CHEROKEE LETTER E;Lo;0;L;;;;;N;;;;;
+13A2;CHEROKEE LETTER I;Lo;0;L;;;;;N;;;;;
+13A3;CHEROKEE LETTER O;Lo;0;L;;;;;N;;;;;
+13A4;CHEROKEE LETTER U;Lo;0;L;;;;;N;;;;;
+13A5;CHEROKEE LETTER V;Lo;0;L;;;;;N;;;;;
+13A6;CHEROKEE LETTER GA;Lo;0;L;;;;;N;;;;;
+13A7;CHEROKEE LETTER KA;Lo;0;L;;;;;N;;;;;
+13A8;CHEROKEE LETTER GE;Lo;0;L;;;;;N;;;;;
+13A9;CHEROKEE LETTER GI;Lo;0;L;;;;;N;;;;;
+13AA;CHEROKEE LETTER GO;Lo;0;L;;;;;N;;;;;
+13AB;CHEROKEE LETTER GU;Lo;0;L;;;;;N;;;;;
+13AC;CHEROKEE LETTER GV;Lo;0;L;;;;;N;;;;;
+13AD;CHEROKEE LETTER HA;Lo;0;L;;;;;N;;;;;
+13AE;CHEROKEE LETTER HE;Lo;0;L;;;;;N;;;;;
+13AF;CHEROKEE LETTER HI;Lo;0;L;;;;;N;;;;;
+13B0;CHEROKEE LETTER HO;Lo;0;L;;;;;N;;;;;
+13B1;CHEROKEE LETTER HU;Lo;0;L;;;;;N;;;;;
+13B2;CHEROKEE LETTER HV;Lo;0;L;;;;;N;;;;;
+13B3;CHEROKEE LETTER LA;Lo;0;L;;;;;N;;;;;
+13B4;CHEROKEE LETTER LE;Lo;0;L;;;;;N;;;;;
+13B5;CHEROKEE LETTER LI;Lo;0;L;;;;;N;;;;;
+13B6;CHEROKEE LETTER LO;Lo;0;L;;;;;N;;;;;
+13B7;CHEROKEE LETTER LU;Lo;0;L;;;;;N;;;;;
+13B8;CHEROKEE LETTER LV;Lo;0;L;;;;;N;;;;;
+13B9;CHEROKEE LETTER MA;Lo;0;L;;;;;N;;;;;
+13BA;CHEROKEE LETTER ME;Lo;0;L;;;;;N;;;;;
+13BB;CHEROKEE LETTER MI;Lo;0;L;;;;;N;;;;;
+13BC;CHEROKEE LETTER MO;Lo;0;L;;;;;N;;;;;
+13BD;CHEROKEE LETTER MU;Lo;0;L;;;;;N;;;;;
+13BE;CHEROKEE LETTER NA;Lo;0;L;;;;;N;;;;;
+13BF;CHEROKEE LETTER HNA;Lo;0;L;;;;;N;;;;;
+13C0;CHEROKEE LETTER NAH;Lo;0;L;;;;;N;;;;;
+13C1;CHEROKEE LETTER NE;Lo;0;L;;;;;N;;;;;
+13C2;CHEROKEE LETTER NI;Lo;0;L;;;;;N;;;;;
+13C3;CHEROKEE LETTER NO;Lo;0;L;;;;;N;;;;;
+13C4;CHEROKEE LETTER NU;Lo;0;L;;;;;N;;;;;
+13C5;CHEROKEE LETTER NV;Lo;0;L;;;;;N;;;;;
+13C6;CHEROKEE LETTER QUA;Lo;0;L;;;;;N;;;;;
+13C7;CHEROKEE LETTER QUE;Lo;0;L;;;;;N;;;;;
+13C8;CHEROKEE LETTER QUI;Lo;0;L;;;;;N;;;;;
+13C9;CHEROKEE LETTER QUO;Lo;0;L;;;;;N;;;;;
+13CA;CHEROKEE LETTER QUU;Lo;0;L;;;;;N;;;;;
+13CB;CHEROKEE LETTER QUV;Lo;0;L;;;;;N;;;;;
+13CC;CHEROKEE LETTER SA;Lo;0;L;;;;;N;;;;;
+13CD;CHEROKEE LETTER S;Lo;0;L;;;;;N;;;;;
+13CE;CHEROKEE LETTER SE;Lo;0;L;;;;;N;;;;;
+13CF;CHEROKEE LETTER SI;Lo;0;L;;;;;N;;;;;
+13D0;CHEROKEE LETTER SO;Lo;0;L;;;;;N;;;;;
+13D1;CHEROKEE LETTER SU;Lo;0;L;;;;;N;;;;;
+13D2;CHEROKEE LETTER SV;Lo;0;L;;;;;N;;;;;
+13D3;CHEROKEE LETTER DA;Lo;0;L;;;;;N;;;;;
+13D4;CHEROKEE LETTER TA;Lo;0;L;;;;;N;;;;;
+13D5;CHEROKEE LETTER DE;Lo;0;L;;;;;N;;;;;
+13D6;CHEROKEE LETTER TE;Lo;0;L;;;;;N;;;;;
+13D7;CHEROKEE LETTER DI;Lo;0;L;;;;;N;;;;;
+13D8;CHEROKEE LETTER TI;Lo;0;L;;;;;N;;;;;
+13D9;CHEROKEE LETTER DO;Lo;0;L;;;;;N;;;;;
+13DA;CHEROKEE LETTER DU;Lo;0;L;;;;;N;;;;;
+13DB;CHEROKEE LETTER DV;Lo;0;L;;;;;N;;;;;
+13DC;CHEROKEE LETTER DLA;Lo;0;L;;;;;N;;;;;
+13DD;CHEROKEE LETTER TLA;Lo;0;L;;;;;N;;;;;
+13DE;CHEROKEE LETTER TLE;Lo;0;L;;;;;N;;;;;
+13DF;CHEROKEE LETTER TLI;Lo;0;L;;;;;N;;;;;
+13E0;CHEROKEE LETTER TLO;Lo;0;L;;;;;N;;;;;
+13E1;CHEROKEE LETTER TLU;Lo;0;L;;;;;N;;;;;
+13E2;CHEROKEE LETTER TLV;Lo;0;L;;;;;N;;;;;
+13E3;CHEROKEE LETTER TSA;Lo;0;L;;;;;N;;;;;
+13E4;CHEROKEE LETTER TSE;Lo;0;L;;;;;N;;;;;
+13E5;CHEROKEE LETTER TSI;Lo;0;L;;;;;N;;;;;
+13E6;CHEROKEE LETTER TSO;Lo;0;L;;;;;N;;;;;
+13E7;CHEROKEE LETTER TSU;Lo;0;L;;;;;N;;;;;
+13E8;CHEROKEE LETTER TSV;Lo;0;L;;;;;N;;;;;
+13E9;CHEROKEE LETTER WA;Lo;0;L;;;;;N;;;;;
+13EA;CHEROKEE LETTER WE;Lo;0;L;;;;;N;;;;;
+13EB;CHEROKEE LETTER WI;Lo;0;L;;;;;N;;;;;
+13EC;CHEROKEE LETTER WO;Lo;0;L;;;;;N;;;;;
+13ED;CHEROKEE LETTER WU;Lo;0;L;;;;;N;;;;;
+13EE;CHEROKEE LETTER WV;Lo;0;L;;;;;N;;;;;
+13EF;CHEROKEE LETTER YA;Lo;0;L;;;;;N;;;;;
+13F0;CHEROKEE LETTER YE;Lo;0;L;;;;;N;;;;;
+13F1;CHEROKEE LETTER YI;Lo;0;L;;;;;N;;;;;
+13F2;CHEROKEE LETTER YO;Lo;0;L;;;;;N;;;;;
+13F3;CHEROKEE LETTER YU;Lo;0;L;;;;;N;;;;;
+13F4;CHEROKEE LETTER YV;Lo;0;L;;;;;N;;;;;
+1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;;
+1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;;
+1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;;
+1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;;
+1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;;
+1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;;
+1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;;
+1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;;
+1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;;
+1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;;
+140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;;
+140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;;
+140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;;
+140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;;
+140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;;
+140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;;
+1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;;
+1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;;
+1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;;
+1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;;
+1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;;
+1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;;
+1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;;
+1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;;
+1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;;
+1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;;
+141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;;
+141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;;
+141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;;
+141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;;
+141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;;
+141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;;
+1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;;
+1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;;
+1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;;
+1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;;
+1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;;
+1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;;
+1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;;
+1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;;
+1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;;
+1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;;
+142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;;
+142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;;
+142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;;
+142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;;
+142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;;
+142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;;
+1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;;
+1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;;
+1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;;
+1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;;
+1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;;
+1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;;
+1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;;
+1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;;
+1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;;
+1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;;
+143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;;
+143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;;
+143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;;
+143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;;
+143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;;
+143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;;
+1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;;
+1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;;
+1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;;
+1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;;
+1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;;
+1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;;
+1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;;
+1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;;
+1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;;
+1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;;
+144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;;
+144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;;
+144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;;
+144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;;
+144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;;
+144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;;
+1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;;
+1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;;
+1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;;
+1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;;
+1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;;
+1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;;
+1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;;
+1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;;
+1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;;
+1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;;
+145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;;
+145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;;
+145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;;
+145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;;
+145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;;
+145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;;
+1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;;
+1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;;
+1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;;
+1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;;
+1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;;
+1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;;
+1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;;
+1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;;
+1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;;
+1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;;
+146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;;
+146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;;
+146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;;
+146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;;
+146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;;
+146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;;
+1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;;
+1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;;
+1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;;
+1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;;
+1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;;
+1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;;
+1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;;
+1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;;
+1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;;
+1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;;
+147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;;
+147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;;
+147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;;
+147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;;
+147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;;
+147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;;
+1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;;
+1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;;
+1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;;
+1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;;
+1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;;
+1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;;
+1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;;
+1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;;
+1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;;
+1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;;
+148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;;
+148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;;
+148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;;
+148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;;
+148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;;
+148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;;
+1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;;
+1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;;
+1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;;
+1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;;
+1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;;
+1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;;
+1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;;
+1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;;
+1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;;
+1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;;
+149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;;
+149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;;
+149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;;
+149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;;
+149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;;
+149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;;
+14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;;
+14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;;
+14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;;
+14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;;
+14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;;
+14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;;
+14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;;
+14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;;
+14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;;
+14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;;
+14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;;
+14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;;
+14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;;
+14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;;
+14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;;
+14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;;
+14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;;
+14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;;
+14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;;
+14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;;
+14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;;
+14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;;
+14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;;
+14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;;
+14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;;
+14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;;
+14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;;
+14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;;
+14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;;
+14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;;
+14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;;
+14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;;
+14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;;
+14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;;
+14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;;
+14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;;
+14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;;
+14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;;
+14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;;
+14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;;
+14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;;
+14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;;
+14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;;
+14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;;
+14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;;
+14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;;
+14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;;
+14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;;
+14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;;
+14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;;
+14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;;
+14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;;
+14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;;
+14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;;
+14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;;
+14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;;
+14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;;
+14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;;
+14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;;
+14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;;
+14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;;
+14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;;
+14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;;
+14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;;
+14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;;
+14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;;
+14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;;
+14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;;
+14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;;
+14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;;
+14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;;
+14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;;
+14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;;
+14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;;
+14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;;
+14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;;
+14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;;
+14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;;
+14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;;
+14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;;
+14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;;
+14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;;
+14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;;
+14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;;
+14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;;
+14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;;
+14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;;
+14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;;
+14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;;
+14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;;
+14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;;
+14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;;
+14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;;
+14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;;
+14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;;
+14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;;
+1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;;
+1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;;
+1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;;
+1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;;
+1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;;
+1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;;
+1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;;
+1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;;
+1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;;
+1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;;
+150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;;
+150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;;
+150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;;
+150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;;
+150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;;
+150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;;
+1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;;
+1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;;
+1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;;
+1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;;
+1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;;
+1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;;
+1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;;
+1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;;
+1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;;
+1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;;
+151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;;
+151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;;
+151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;;
+151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;;
+151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;;
+151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;;
+1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;;
+1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;;
+1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;;
+1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;;
+1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;;
+1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;;
+1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;;
+1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;;
+1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;;
+1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;;
+152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;;
+152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;;
+152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;;
+152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;;
+152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;;
+152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;;
+1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;;
+1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;;
+1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;;
+1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;;
+1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;;
+1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;;
+1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;;
+1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;;
+1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;;
+1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;;
+153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;;
+153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;;
+153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;;
+153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;;
+153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;;
+153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;;
+1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;;
+1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;;
+1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;;
+1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;;
+1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;;
+1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;;
+1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;;
+1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;;
+1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;;
+1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;;
+154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;;
+154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;;
+154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;;
+154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;;
+154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;;
+154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;;
+1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;;
+1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;;
+1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;;
+1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;;
+1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;;
+1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;;
+1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;;
+1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;;
+1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;;
+1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;;
+155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;;
+155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;;
+155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;;
+155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;;
+155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;;
+155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;;
+1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;;
+1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;;
+1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;;
+1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;;
+1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;;
+1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;;
+1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;;
+1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;;
+1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;;
+1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;;
+156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;;
+156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;;
+156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;;
+156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;;
+156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;;
+156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;;
+1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;;
+1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;;
+1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;;
+1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;;
+1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;;
+1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;;
+1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;;
+1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;;
+1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;;
+1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;;
+157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;;
+157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;;
+157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;;
+157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;;
+157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;;
+157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;;
+1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;;
+1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;;
+1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;;
+1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;;
+1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;;
+1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;;
+1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;;
+1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;;
+1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;;
+1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;;
+158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;;
+158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;;
+158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;;
+158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;;
+158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;;
+158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;;
+1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;;
+1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;;
+1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;;
+1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;;
+1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;;
+1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;;
+1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;;
+1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;;
+1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;;
+1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;;
+159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;;
+159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;;
+159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;;
+159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;;
+159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;;
+159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;;
+15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;;
+15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;;
+15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;;
+15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;;
+15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;;
+15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;;
+15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;;
+15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;;
+15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;;
+15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;;
+15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;;
+15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;;
+15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;;
+15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;;
+15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;;
+15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;;
+15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;;
+15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;;
+15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;;
+15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;;
+15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;;
+15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;;
+15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;;
+15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;;
+15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;;
+15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;;
+15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;;
+15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;;
+15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;;
+15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;;
+15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;;
+15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;;
+15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;;
+15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;;
+15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;;
+15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;;
+15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;;
+15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;;
+15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;;
+15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;;
+15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;;
+15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;;
+15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;;
+15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;;
+15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;;
+15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;;
+15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;;
+15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;;
+15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;;
+15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;;
+15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;;
+15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;;
+15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;;
+15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;;
+15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;;
+15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;;
+15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;;
+15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;;
+15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;;
+15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;;
+15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;;
+15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;;
+15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;;
+15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;;
+15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;;
+15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;;
+15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;;
+15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;;
+15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;;
+15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;;
+15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;;
+15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;;
+15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;;
+15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;;
+15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;;
+15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;;
+15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;;
+15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;;
+15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;;
+15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;;
+15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;;
+15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;;
+15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;;
+15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;;
+15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;;
+15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;;
+15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;;
+15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;;
+15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;;
+15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;;
+15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;;
+15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;;
+15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;;
+15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;;
+15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;;
+15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;;
+1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;;
+1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;;
+1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;;
+1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;;
+1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;;
+1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;;
+1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;;
+1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;;
+1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;;
+1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;;
+160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;;
+160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;;
+160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;;
+160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;;
+160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;;
+160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;;
+1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;;
+1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;;
+1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;;
+1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;;
+1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;;
+1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;;
+1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;;
+1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;;
+1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;;
+1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;;
+161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;;
+161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;;
+161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;;
+161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;;
+161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;;
+161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;;
+1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;;
+1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;;
+1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;;
+1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;;
+1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;;
+1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;;
+1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;;
+1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;;
+1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;;
+1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;;
+162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;;
+162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;;
+162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;;
+162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;;
+162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;;
+162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;;
+1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;;
+1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;;
+1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;;
+1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;;
+1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;;
+1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;;
+1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;;
+1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;;
+1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;;
+1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;;
+163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;;
+163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;;
+163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;;
+163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;;
+163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;;
+163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;;
+1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;;
+1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;;
+1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;;
+1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;;
+1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;;
+1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;;
+1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;;
+1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;;
+1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;;
+1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;;
+164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;;
+164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;;
+164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;;
+164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;;
+164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;;
+164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;;
+1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;;
+1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;;
+1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;;
+1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;;
+1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;;
+1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;;
+1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;;
+1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;;
+1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;;
+1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;;
+165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;;
+165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;;
+165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;;
+165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;;
+165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;;
+165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;;
+1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;;
+1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;;
+1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;;
+1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;;
+1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;;
+1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;;
+1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;;
+1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;;
+1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;;
+1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;;
+166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;;
+166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;;
+166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;;
+166D;CANADIAN SYLLABICS CHI SIGN;Po;0;L;;;;;N;;;;;
+166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;;
+166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;;
+1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;;
+1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;;
+1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;;
+1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;;
+1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;;
+1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;;
+1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;;
+1677;CANADIAN SYLLABICS WOODS-CREE THWEE;Lo;0;L;;;;;N;;;;;
+1678;CANADIAN SYLLABICS WOODS-CREE THWI;Lo;0;L;;;;;N;;;;;
+1679;CANADIAN SYLLABICS WOODS-CREE THWII;Lo;0;L;;;;;N;;;;;
+167A;CANADIAN SYLLABICS WOODS-CREE THWO;Lo;0;L;;;;;N;;;;;
+167B;CANADIAN SYLLABICS WOODS-CREE THWOO;Lo;0;L;;;;;N;;;;;
+167C;CANADIAN SYLLABICS WOODS-CREE THWA;Lo;0;L;;;;;N;;;;;
+167D;CANADIAN SYLLABICS WOODS-CREE THWAA;Lo;0;L;;;;;N;;;;;
+167E;CANADIAN SYLLABICS WOODS-CREE FINAL TH;Lo;0;L;;;;;N;;;;;
+167F;CANADIAN SYLLABICS BLACKFOOT W;Lo;0;L;;;;;N;;;;;
+1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
+1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;;
+1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;;
+1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;;
+1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;;
+1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;;
+1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;;
+1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;;
+1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;;
+1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;;
+168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;;
+168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;;
+168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;;
+168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;;
+168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;;
+168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;;
+1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;;
+1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;;
+1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;;
+1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;;
+1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;;
+1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;;
+1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;;
+1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;;
+1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;;
+1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;;
+169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;;
+169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;Y;;;;;
+169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;Y;;;;;
+16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;;
+16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;;
+16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;;
+16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;;
+16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;;
+16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;;
+16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;;
+16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;;
+16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;;
+16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;;
+16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;;
+16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;;
+16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;;
+16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;;
+16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;;
+16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;;
+16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;;
+16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;;
+16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;;
+16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;;
+16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;;
+16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;;
+16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;;
+16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;;
+16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;;
+16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;;
+16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;;
+16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;;
+16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;;
+16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;;
+16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;;
+16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;;
+16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;;
+16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;;
+16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;;
+16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;;
+16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;;
+16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;;
+16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;;
+16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;;
+16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;;
+16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;;
+16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;;
+16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;;
+16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;;
+16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;;
+16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;;
+16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;;
+16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;;
+16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;;
+16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;;
+16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;;
+16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;;
+16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;;
+16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;;
+16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;;
+16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;;
+16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;;
+16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;;
+16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;;
+16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;;
+16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;;
+16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;;
+16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;;
+16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;;
+16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;;
+16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;;
+16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;;
+16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;;
+16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;;
+16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;;
+16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;;
+16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;;
+16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;;
+16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;;
+16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;;
+16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;;
+16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;;
+16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;;;;
+16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;;;;
+16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;;;;
+1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;;
+1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;;
+1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;;
+1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;;
+1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;;
+1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;;
+1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;;
+1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;;
+1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;;
+1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;;
+170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;;
+170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;;
+170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;;
+170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;;
+170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;;
+1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;;
+1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;;
+1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;;
+1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;;
+1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;;
+1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;;
+1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;;
+1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;;
+1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;;
+1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;;
+1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;;
+1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;;
+172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;;
+172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;;
+172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;;
+172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;;
+172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;;
+172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;;
+1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;;
+1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;;
+1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;;
+1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;;
+1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;;
+1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;;
+1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;;
+1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;;
+1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;;
+1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;;
+1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;;
+1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;;
+1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;;
+1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;;
+1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;;
+174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;;
+174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;;
+174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;;
+174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;;
+174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;;
+174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;;
+1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;;
+1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;;
+1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;;
+1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;;
+1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;;
+1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;;
+1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;;
+1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;;
+1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;;
+1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;;
+1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;;
+1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;;
+176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;;
+176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;;
+176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;;
+176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;;
+176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;;
+1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;;
+1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;;
+1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;;
+1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;;
+1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;;
+1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;;
+1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;;
+1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;;
+1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;;
+1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;;
+1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;;
+178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;;
+178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;;
+178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;;
+178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;;
+178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;;
+178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;;
+1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;;
+1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;;
+1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;;
+1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;;
+1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;;
+1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;;
+1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;;
+1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;;
+1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;;
+1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;;
+179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;;
+179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;;
+179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;;
+179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;;
+179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;;
+179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;;
+17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;;
+17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;;
+17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;;
+17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;;
+17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;;
+17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;;
+17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;;
+17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;;
+17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;;
+17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;;
+17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;;
+17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;;
+17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;;
+17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;;
+17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;;
+17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;;
+17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;;
+17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;;
+17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;;
+17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;;
+17B4;KHMER VOWEL INHERENT AQ;Cf;0;L;;;;;N;;;;;
+17B5;KHMER VOWEL INHERENT AA;Cf;0;L;;;;;N;;;;;
+17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;;
+17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;;
+17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;;
+17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;;
+17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;;
+17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;;
+17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
+17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
+17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;;
+17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;;
+17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;;
+17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;;
+17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;;
+17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;;
+17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;;
+17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;;
+17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;;
+17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;;
+17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;;
+17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;;
+17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;;
+17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;;
+17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;;
+17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;;
+17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;;
+17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;;
+17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;;
+17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;;
+17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;;
+17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;;
+17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;;
+17DD;KHMER SIGN ATTHACAN;Mn;230;NSM;;;;;N;;;;;
+17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+17F0;KHMER SYMBOL LEK ATTAK SON;No;0;ON;;;;0;N;;;;;
+17F1;KHMER SYMBOL LEK ATTAK MUOY;No;0;ON;;;;1;N;;;;;
+17F2;KHMER SYMBOL LEK ATTAK PII;No;0;ON;;;;2;N;;;;;
+17F3;KHMER SYMBOL LEK ATTAK BEI;No;0;ON;;;;3;N;;;;;
+17F4;KHMER SYMBOL LEK ATTAK BUON;No;0;ON;;;;4;N;;;;;
+17F5;KHMER SYMBOL LEK ATTAK PRAM;No;0;ON;;;;5;N;;;;;
+17F6;KHMER SYMBOL LEK ATTAK PRAM-MUOY;No;0;ON;;;;6;N;;;;;
+17F7;KHMER SYMBOL LEK ATTAK PRAM-PII;No;0;ON;;;;7;N;;;;;
+17F8;KHMER SYMBOL LEK ATTAK PRAM-BEI;No;0;ON;;;;8;N;;;;;
+17F9;KHMER SYMBOL LEK ATTAK PRAM-BUON;No;0;ON;;;;9;N;;;;;
+1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;;
+1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;;
+1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;;
+1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;;
+1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;;
+1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;;
+1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;;
+1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;;
+1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;;
+1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;;
+180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;;
+180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;;
+180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;;
+180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;;
+180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
+1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;;
+1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;;
+1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;;
+1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;;
+1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;;
+1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;;
+1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;;
+1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;;
+1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;;
+1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;;
+182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;;
+182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;;
+182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;;
+182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;;
+182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;;
+182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;;
+1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;;
+1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;;
+1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;;
+1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;;
+1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;;
+1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;;
+1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;;
+1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;;
+1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;;
+1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;;
+183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;;
+183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;;
+183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;;
+183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;;
+183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;;
+183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;;
+1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;;
+1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;;
+1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;;
+1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;;
+1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;;
+1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;;
+1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;;
+1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;;
+1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;;
+1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;;
+184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;;
+184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;;
+184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;;
+184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;;
+184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;;
+184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;;
+1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;;
+1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;;
+1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;;
+1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;;
+1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;;
+1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;;
+1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;;
+1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;;
+1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;;
+1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;;
+185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;;
+185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;;
+185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;;
+185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;;
+185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;;
+185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;;
+1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;;
+1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;;
+1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;;
+1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;;
+1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;;
+1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;;
+1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;;
+1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;;
+1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;;
+1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;;
+186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;;
+186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;;
+186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;;
+186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;;
+186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;;
+186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;;
+1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;;
+1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;;
+1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;;
+1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;;
+1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;;
+1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;;
+1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;;
+1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;;
+1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;;
+1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;;
+1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;;
+1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;;
+1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;;
+1885;MONGOLIAN LETTER ALI GALI BALUDA;Lo;0;L;;;;;N;;;;;
+1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Lo;0;L;;;;;N;;;;;
+1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;;
+1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;;
+1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;;
+188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;;
+188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;;
+188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;;
+188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;;
+188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;;
+188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;;
+1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;;
+1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;;
+1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;;
+1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;;
+1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;;
+1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;;
+1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;;
+1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;;
+1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;;
+1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;;
+189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;;
+189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;;
+189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;;
+189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;;
+189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;;
+189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;;
+18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;;
+18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;;
+18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;;
+18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;;
+18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;;
+18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;;
+18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;;
+18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;;
+18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;;
+18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;;
+18AA;MONGOLIAN LETTER MANCHU ALI GALI LHA;Lo;0;L;;;;;N;;;;;
+18B0;CANADIAN SYLLABICS OY;Lo;0;L;;;;;N;;;;;
+18B1;CANADIAN SYLLABICS AY;Lo;0;L;;;;;N;;;;;
+18B2;CANADIAN SYLLABICS AAY;Lo;0;L;;;;;N;;;;;
+18B3;CANADIAN SYLLABICS WAY;Lo;0;L;;;;;N;;;;;
+18B4;CANADIAN SYLLABICS POY;Lo;0;L;;;;;N;;;;;
+18B5;CANADIAN SYLLABICS PAY;Lo;0;L;;;;;N;;;;;
+18B6;CANADIAN SYLLABICS PWOY;Lo;0;L;;;;;N;;;;;
+18B7;CANADIAN SYLLABICS TAY;Lo;0;L;;;;;N;;;;;
+18B8;CANADIAN SYLLABICS KAY;Lo;0;L;;;;;N;;;;;
+18B9;CANADIAN SYLLABICS KWAY;Lo;0;L;;;;;N;;;;;
+18BA;CANADIAN SYLLABICS MAY;Lo;0;L;;;;;N;;;;;
+18BB;CANADIAN SYLLABICS NOY;Lo;0;L;;;;;N;;;;;
+18BC;CANADIAN SYLLABICS NAY;Lo;0;L;;;;;N;;;;;
+18BD;CANADIAN SYLLABICS LAY;Lo;0;L;;;;;N;;;;;
+18BE;CANADIAN SYLLABICS SOY;Lo;0;L;;;;;N;;;;;
+18BF;CANADIAN SYLLABICS SAY;Lo;0;L;;;;;N;;;;;
+18C0;CANADIAN SYLLABICS SHOY;Lo;0;L;;;;;N;;;;;
+18C1;CANADIAN SYLLABICS SHAY;Lo;0;L;;;;;N;;;;;
+18C2;CANADIAN SYLLABICS SHWOY;Lo;0;L;;;;;N;;;;;
+18C3;CANADIAN SYLLABICS YOY;Lo;0;L;;;;;N;;;;;
+18C4;CANADIAN SYLLABICS YAY;Lo;0;L;;;;;N;;;;;
+18C5;CANADIAN SYLLABICS RAY;Lo;0;L;;;;;N;;;;;
+18C6;CANADIAN SYLLABICS NWI;Lo;0;L;;;;;N;;;;;
+18C7;CANADIAN SYLLABICS OJIBWAY NWI;Lo;0;L;;;;;N;;;;;
+18C8;CANADIAN SYLLABICS NWII;Lo;0;L;;;;;N;;;;;
+18C9;CANADIAN SYLLABICS OJIBWAY NWII;Lo;0;L;;;;;N;;;;;
+18CA;CANADIAN SYLLABICS NWO;Lo;0;L;;;;;N;;;;;
+18CB;CANADIAN SYLLABICS OJIBWAY NWO;Lo;0;L;;;;;N;;;;;
+18CC;CANADIAN SYLLABICS NWOO;Lo;0;L;;;;;N;;;;;
+18CD;CANADIAN SYLLABICS OJIBWAY NWOO;Lo;0;L;;;;;N;;;;;
+18CE;CANADIAN SYLLABICS RWEE;Lo;0;L;;;;;N;;;;;
+18CF;CANADIAN SYLLABICS RWI;Lo;0;L;;;;;N;;;;;
+18D0;CANADIAN SYLLABICS RWII;Lo;0;L;;;;;N;;;;;
+18D1;CANADIAN SYLLABICS RWO;Lo;0;L;;;;;N;;;;;
+18D2;CANADIAN SYLLABICS RWOO;Lo;0;L;;;;;N;;;;;
+18D3;CANADIAN SYLLABICS RWA;Lo;0;L;;;;;N;;;;;
+18D4;CANADIAN SYLLABICS OJIBWAY P;Lo;0;L;;;;;N;;;;;
+18D5;CANADIAN SYLLABICS OJIBWAY T;Lo;0;L;;;;;N;;;;;
+18D6;CANADIAN SYLLABICS OJIBWAY K;Lo;0;L;;;;;N;;;;;
+18D7;CANADIAN SYLLABICS OJIBWAY C;Lo;0;L;;;;;N;;;;;
+18D8;CANADIAN SYLLABICS OJIBWAY M;Lo;0;L;;;;;N;;;;;
+18D9;CANADIAN SYLLABICS OJIBWAY N;Lo;0;L;;;;;N;;;;;
+18DA;CANADIAN SYLLABICS OJIBWAY S;Lo;0;L;;;;;N;;;;;
+18DB;CANADIAN SYLLABICS OJIBWAY SH;Lo;0;L;;;;;N;;;;;
+18DC;CANADIAN SYLLABICS EASTERN W;Lo;0;L;;;;;N;;;;;
+18DD;CANADIAN SYLLABICS WESTERN W;Lo;0;L;;;;;N;;;;;
+18DE;CANADIAN SYLLABICS FINAL SMALL RING;Lo;0;L;;;;;N;;;;;
+18DF;CANADIAN SYLLABICS FINAL RAISED DOT;Lo;0;L;;;;;N;;;;;
+18E0;CANADIAN SYLLABICS R-CREE RWE;Lo;0;L;;;;;N;;;;;
+18E1;CANADIAN SYLLABICS WEST-CREE LOO;Lo;0;L;;;;;N;;;;;
+18E2;CANADIAN SYLLABICS WEST-CREE LAA;Lo;0;L;;;;;N;;;;;
+18E3;CANADIAN SYLLABICS THWE;Lo;0;L;;;;;N;;;;;
+18E4;CANADIAN SYLLABICS THWA;Lo;0;L;;;;;N;;;;;
+18E5;CANADIAN SYLLABICS TTHWE;Lo;0;L;;;;;N;;;;;
+18E6;CANADIAN SYLLABICS TTHOO;Lo;0;L;;;;;N;;;;;
+18E7;CANADIAN SYLLABICS TTHAA;Lo;0;L;;;;;N;;;;;
+18E8;CANADIAN SYLLABICS TLHWE;Lo;0;L;;;;;N;;;;;
+18E9;CANADIAN SYLLABICS TLHOO;Lo;0;L;;;;;N;;;;;
+18EA;CANADIAN SYLLABICS SAYISI SHWE;Lo;0;L;;;;;N;;;;;
+18EB;CANADIAN SYLLABICS SAYISI SHOO;Lo;0;L;;;;;N;;;;;
+18EC;CANADIAN SYLLABICS SAYISI HOO;Lo;0;L;;;;;N;;;;;
+18ED;CANADIAN SYLLABICS CARRIER GWU;Lo;0;L;;;;;N;;;;;
+18EE;CANADIAN SYLLABICS CARRIER DENE GEE;Lo;0;L;;;;;N;;;;;
+18EF;CANADIAN SYLLABICS CARRIER GAA;Lo;0;L;;;;;N;;;;;
+18F0;CANADIAN SYLLABICS CARRIER GWA;Lo;0;L;;;;;N;;;;;
+18F1;CANADIAN SYLLABICS SAYISI JUU;Lo;0;L;;;;;N;;;;;
+18F2;CANADIAN SYLLABICS CARRIER JWA;Lo;0;L;;;;;N;;;;;
+18F3;CANADIAN SYLLABICS BEAVER DENE L;Lo;0;L;;;;;N;;;;;
+18F4;CANADIAN SYLLABICS BEAVER DENE R;Lo;0;L;;;;;N;;;;;
+18F5;CANADIAN SYLLABICS CARRIER DENTAL S;Lo;0;L;;;;;N;;;;;
+1900;LIMBU VOWEL-CARRIER LETTER;Lo;0;L;;;;;N;;;;;
+1901;LIMBU LETTER KA;Lo;0;L;;;;;N;;;;;
+1902;LIMBU LETTER KHA;Lo;0;L;;;;;N;;;;;
+1903;LIMBU LETTER GA;Lo;0;L;;;;;N;;;;;
+1904;LIMBU LETTER GHA;Lo;0;L;;;;;N;;;;;
+1905;LIMBU LETTER NGA;Lo;0;L;;;;;N;;;;;
+1906;LIMBU LETTER CA;Lo;0;L;;;;;N;;;;;
+1907;LIMBU LETTER CHA;Lo;0;L;;;;;N;;;;;
+1908;LIMBU LETTER JA;Lo;0;L;;;;;N;;;;;
+1909;LIMBU LETTER JHA;Lo;0;L;;;;;N;;;;;
+190A;LIMBU LETTER YAN;Lo;0;L;;;;;N;;;;;
+190B;LIMBU LETTER TA;Lo;0;L;;;;;N;;;;;
+190C;LIMBU LETTER THA;Lo;0;L;;;;;N;;;;;
+190D;LIMBU LETTER DA;Lo;0;L;;;;;N;;;;;
+190E;LIMBU LETTER DHA;Lo;0;L;;;;;N;;;;;
+190F;LIMBU LETTER NA;Lo;0;L;;;;;N;;;;;
+1910;LIMBU LETTER PA;Lo;0;L;;;;;N;;;;;
+1911;LIMBU LETTER PHA;Lo;0;L;;;;;N;;;;;
+1912;LIMBU LETTER BA;Lo;0;L;;;;;N;;;;;
+1913;LIMBU LETTER BHA;Lo;0;L;;;;;N;;;;;
+1914;LIMBU LETTER MA;Lo;0;L;;;;;N;;;;;
+1915;LIMBU LETTER YA;Lo;0;L;;;;;N;;;;;
+1916;LIMBU LETTER RA;Lo;0;L;;;;;N;;;;;
+1917;LIMBU LETTER LA;Lo;0;L;;;;;N;;;;;
+1918;LIMBU LETTER WA;Lo;0;L;;;;;N;;;;;
+1919;LIMBU LETTER SHA;Lo;0;L;;;;;N;;;;;
+191A;LIMBU LETTER SSA;Lo;0;L;;;;;N;;;;;
+191B;LIMBU LETTER SA;Lo;0;L;;;;;N;;;;;
+191C;LIMBU LETTER HA;Lo;0;L;;;;;N;;;;;
+1920;LIMBU VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;;
+1921;LIMBU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+1922;LIMBU VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+1923;LIMBU VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
+1924;LIMBU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+1925;LIMBU VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
+1926;LIMBU VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+1927;LIMBU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+1928;LIMBU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+1929;LIMBU SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;;
+192A;LIMBU SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;;
+192B;LIMBU SUBJOINED LETTER WA;Mc;0;L;;;;;N;;;;;
+1930;LIMBU SMALL LETTER KA;Mc;0;L;;;;;N;;;;;
+1931;LIMBU SMALL LETTER NGA;Mc;0;L;;;;;N;;;;;
+1932;LIMBU SMALL LETTER ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+1933;LIMBU SMALL LETTER TA;Mc;0;L;;;;;N;;;;;
+1934;LIMBU SMALL LETTER NA;Mc;0;L;;;;;N;;;;;
+1935;LIMBU SMALL LETTER PA;Mc;0;L;;;;;N;;;;;
+1936;LIMBU SMALL LETTER MA;Mc;0;L;;;;;N;;;;;
+1937;LIMBU SMALL LETTER RA;Mc;0;L;;;;;N;;;;;
+1938;LIMBU SMALL LETTER LA;Mc;0;L;;;;;N;;;;;
+1939;LIMBU SIGN MUKPHRENG;Mn;222;NSM;;;;;N;;;;;
+193A;LIMBU SIGN KEMPHRENG;Mn;230;NSM;;;;;N;;;;;
+193B;LIMBU SIGN SA-I;Mn;220;NSM;;;;;N;;;;;
+1940;LIMBU SIGN LOO;So;0;ON;;;;;N;;;;;
+1944;LIMBU EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
+1945;LIMBU QUESTION MARK;Po;0;ON;;;;;N;;;;;
+1946;LIMBU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1947;LIMBU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1948;LIMBU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1949;LIMBU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+194A;LIMBU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+194B;LIMBU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+194C;LIMBU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+194D;LIMBU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+194E;LIMBU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+194F;LIMBU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1950;TAI LE LETTER KA;Lo;0;L;;;;;N;;;;;
+1951;TAI LE LETTER XA;Lo;0;L;;;;;N;;;;;
+1952;TAI LE LETTER NGA;Lo;0;L;;;;;N;;;;;
+1953;TAI LE LETTER TSA;Lo;0;L;;;;;N;;;;;
+1954;TAI LE LETTER SA;Lo;0;L;;;;;N;;;;;
+1955;TAI LE LETTER YA;Lo;0;L;;;;;N;;;;;
+1956;TAI LE LETTER TA;Lo;0;L;;;;;N;;;;;
+1957;TAI LE LETTER THA;Lo;0;L;;;;;N;;;;;
+1958;TAI LE LETTER LA;Lo;0;L;;;;;N;;;;;
+1959;TAI LE LETTER PA;Lo;0;L;;;;;N;;;;;
+195A;TAI LE LETTER PHA;Lo;0;L;;;;;N;;;;;
+195B;TAI LE LETTER MA;Lo;0;L;;;;;N;;;;;
+195C;TAI LE LETTER FA;Lo;0;L;;;;;N;;;;;
+195D;TAI LE LETTER VA;Lo;0;L;;;;;N;;;;;
+195E;TAI LE LETTER HA;Lo;0;L;;;;;N;;;;;
+195F;TAI LE LETTER QA;Lo;0;L;;;;;N;;;;;
+1960;TAI LE LETTER KHA;Lo;0;L;;;;;N;;;;;
+1961;TAI LE LETTER TSHA;Lo;0;L;;;;;N;;;;;
+1962;TAI LE LETTER NA;Lo;0;L;;;;;N;;;;;
+1963;TAI LE LETTER A;Lo;0;L;;;;;N;;;;;
+1964;TAI LE LETTER I;Lo;0;L;;;;;N;;;;;
+1965;TAI LE LETTER EE;Lo;0;L;;;;;N;;;;;
+1966;TAI LE LETTER EH;Lo;0;L;;;;;N;;;;;
+1967;TAI LE LETTER U;Lo;0;L;;;;;N;;;;;
+1968;TAI LE LETTER OO;Lo;0;L;;;;;N;;;;;
+1969;TAI LE LETTER O;Lo;0;L;;;;;N;;;;;
+196A;TAI LE LETTER UE;Lo;0;L;;;;;N;;;;;
+196B;TAI LE LETTER E;Lo;0;L;;;;;N;;;;;
+196C;TAI LE LETTER AUE;Lo;0;L;;;;;N;;;;;
+196D;TAI LE LETTER AI;Lo;0;L;;;;;N;;;;;
+1970;TAI LE LETTER TONE-2;Lo;0;L;;;;;N;;;;;
+1971;TAI LE LETTER TONE-3;Lo;0;L;;;;;N;;;;;
+1972;TAI LE LETTER TONE-4;Lo;0;L;;;;;N;;;;;
+1973;TAI LE LETTER TONE-5;Lo;0;L;;;;;N;;;;;
+1974;TAI LE LETTER TONE-6;Lo;0;L;;;;;N;;;;;
+1980;NEW TAI LUE LETTER HIGH QA;Lo;0;L;;;;;N;;;;;
+1981;NEW TAI LUE LETTER LOW QA;Lo;0;L;;;;;N;;;;;
+1982;NEW TAI LUE LETTER HIGH KA;Lo;0;L;;;;;N;;;;;
+1983;NEW TAI LUE LETTER HIGH XA;Lo;0;L;;;;;N;;;;;
+1984;NEW TAI LUE LETTER HIGH NGA;Lo;0;L;;;;;N;;;;;
+1985;NEW TAI LUE LETTER LOW KA;Lo;0;L;;;;;N;;;;;
+1986;NEW TAI LUE LETTER LOW XA;Lo;0;L;;;;;N;;;;;
+1987;NEW TAI LUE LETTER LOW NGA;Lo;0;L;;;;;N;;;;;
+1988;NEW TAI LUE LETTER HIGH TSA;Lo;0;L;;;;;N;;;;;
+1989;NEW TAI LUE LETTER HIGH SA;Lo;0;L;;;;;N;;;;;
+198A;NEW TAI LUE LETTER HIGH YA;Lo;0;L;;;;;N;;;;;
+198B;NEW TAI LUE LETTER LOW TSA;Lo;0;L;;;;;N;;;;;
+198C;NEW TAI LUE LETTER LOW SA;Lo;0;L;;;;;N;;;;;
+198D;NEW TAI LUE LETTER LOW YA;Lo;0;L;;;;;N;;;;;
+198E;NEW TAI LUE LETTER HIGH TA;Lo;0;L;;;;;N;;;;;
+198F;NEW TAI LUE LETTER HIGH THA;Lo;0;L;;;;;N;;;;;
+1990;NEW TAI LUE LETTER HIGH NA;Lo;0;L;;;;;N;;;;;
+1991;NEW TAI LUE LETTER LOW TA;Lo;0;L;;;;;N;;;;;
+1992;NEW TAI LUE LETTER LOW THA;Lo;0;L;;;;;N;;;;;
+1993;NEW TAI LUE LETTER LOW NA;Lo;0;L;;;;;N;;;;;
+1994;NEW TAI LUE LETTER HIGH PA;Lo;0;L;;;;;N;;;;;
+1995;NEW TAI LUE LETTER HIGH PHA;Lo;0;L;;;;;N;;;;;
+1996;NEW TAI LUE LETTER HIGH MA;Lo;0;L;;;;;N;;;;;
+1997;NEW TAI LUE LETTER LOW PA;Lo;0;L;;;;;N;;;;;
+1998;NEW TAI LUE LETTER LOW PHA;Lo;0;L;;;;;N;;;;;
+1999;NEW TAI LUE LETTER LOW MA;Lo;0;L;;;;;N;;;;;
+199A;NEW TAI LUE LETTER HIGH FA;Lo;0;L;;;;;N;;;;;
+199B;NEW TAI LUE LETTER HIGH VA;Lo;0;L;;;;;N;;;;;
+199C;NEW TAI LUE LETTER HIGH LA;Lo;0;L;;;;;N;;;;;
+199D;NEW TAI LUE LETTER LOW FA;Lo;0;L;;;;;N;;;;;
+199E;NEW TAI LUE LETTER LOW VA;Lo;0;L;;;;;N;;;;;
+199F;NEW TAI LUE LETTER LOW LA;Lo;0;L;;;;;N;;;;;
+19A0;NEW TAI LUE LETTER HIGH HA;Lo;0;L;;;;;N;;;;;
+19A1;NEW TAI LUE LETTER HIGH DA;Lo;0;L;;;;;N;;;;;
+19A2;NEW TAI LUE LETTER HIGH BA;Lo;0;L;;;;;N;;;;;
+19A3;NEW TAI LUE LETTER LOW HA;Lo;0;L;;;;;N;;;;;
+19A4;NEW TAI LUE LETTER LOW DA;Lo;0;L;;;;;N;;;;;
+19A5;NEW TAI LUE LETTER LOW BA;Lo;0;L;;;;;N;;;;;
+19A6;NEW TAI LUE LETTER HIGH KVA;Lo;0;L;;;;;N;;;;;
+19A7;NEW TAI LUE LETTER HIGH XVA;Lo;0;L;;;;;N;;;;;
+19A8;NEW TAI LUE LETTER LOW KVA;Lo;0;L;;;;;N;;;;;
+19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;;
+19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;;
+19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;;
+19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Mc;0;L;;;;;N;;;;;
+19B1;NEW TAI LUE VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+19B2;NEW TAI LUE VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+19B3;NEW TAI LUE VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
+19B4;NEW TAI LUE VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
+19B5;NEW TAI LUE VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+19B6;NEW TAI LUE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
+19B7;NEW TAI LUE VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+19B8;NEW TAI LUE VOWEL SIGN OA;Mc;0;L;;;;;N;;;;;
+19B9;NEW TAI LUE VOWEL SIGN UE;Mc;0;L;;;;;N;;;;;
+19BA;NEW TAI LUE VOWEL SIGN AY;Mc;0;L;;;;;N;;;;;
+19BB;NEW TAI LUE VOWEL SIGN AAY;Mc;0;L;;;;;N;;;;;
+19BC;NEW TAI LUE VOWEL SIGN UY;Mc;0;L;;;;;N;;;;;
+19BD;NEW TAI LUE VOWEL SIGN OY;Mc;0;L;;;;;N;;;;;
+19BE;NEW TAI LUE VOWEL SIGN OAY;Mc;0;L;;;;;N;;;;;
+19BF;NEW TAI LUE VOWEL SIGN UEY;Mc;0;L;;;;;N;;;;;
+19C0;NEW TAI LUE VOWEL SIGN IY;Mc;0;L;;;;;N;;;;;
+19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;;
+19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;;
+19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;;
+19C4;NEW TAI LUE LETTER FINAL M;Lo;0;L;;;;;N;;;;;
+19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;;
+19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;;
+19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;;
+19C8;NEW TAI LUE TONE MARK-1;Mc;0;L;;;;;N;;;;;
+19C9;NEW TAI LUE TONE MARK-2;Mc;0;L;;;;;N;;;;;
+19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+19D3;NEW TAI LUE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+19D4;NEW TAI LUE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+19D5;NEW TAI LUE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+19D6;NEW TAI LUE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+19DA;NEW TAI LUE THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+19DE;NEW TAI LUE SIGN LAE;Po;0;ON;;;;;N;;;;;
+19DF;NEW TAI LUE SIGN LAEV;Po;0;ON;;;;;N;;;;;
+19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;;
+19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;;
+19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;;
+19E3;KHMER SYMBOL BEI KOET;So;0;ON;;;;;N;;;;;
+19E4;KHMER SYMBOL BUON KOET;So;0;ON;;;;;N;;;;;
+19E5;KHMER SYMBOL PRAM KOET;So;0;ON;;;;;N;;;;;
+19E6;KHMER SYMBOL PRAM-MUOY KOET;So;0;ON;;;;;N;;;;;
+19E7;KHMER SYMBOL PRAM-PII KOET;So;0;ON;;;;;N;;;;;
+19E8;KHMER SYMBOL PRAM-BEI KOET;So;0;ON;;;;;N;;;;;
+19E9;KHMER SYMBOL PRAM-BUON KOET;So;0;ON;;;;;N;;;;;
+19EA;KHMER SYMBOL DAP KOET;So;0;ON;;;;;N;;;;;
+19EB;KHMER SYMBOL DAP-MUOY KOET;So;0;ON;;;;;N;;;;;
+19EC;KHMER SYMBOL DAP-PII KOET;So;0;ON;;;;;N;;;;;
+19ED;KHMER SYMBOL DAP-BEI KOET;So;0;ON;;;;;N;;;;;
+19EE;KHMER SYMBOL DAP-BUON KOET;So;0;ON;;;;;N;;;;;
+19EF;KHMER SYMBOL DAP-PRAM KOET;So;0;ON;;;;;N;;;;;
+19F0;KHMER SYMBOL TUTEYASAT;So;0;ON;;;;;N;;;;;
+19F1;KHMER SYMBOL MUOY ROC;So;0;ON;;;;;N;;;;;
+19F2;KHMER SYMBOL PII ROC;So;0;ON;;;;;N;;;;;
+19F3;KHMER SYMBOL BEI ROC;So;0;ON;;;;;N;;;;;
+19F4;KHMER SYMBOL BUON ROC;So;0;ON;;;;;N;;;;;
+19F5;KHMER SYMBOL PRAM ROC;So;0;ON;;;;;N;;;;;
+19F6;KHMER SYMBOL PRAM-MUOY ROC;So;0;ON;;;;;N;;;;;
+19F7;KHMER SYMBOL PRAM-PII ROC;So;0;ON;;;;;N;;;;;
+19F8;KHMER SYMBOL PRAM-BEI ROC;So;0;ON;;;;;N;;;;;
+19F9;KHMER SYMBOL PRAM-BUON ROC;So;0;ON;;;;;N;;;;;
+19FA;KHMER SYMBOL DAP ROC;So;0;ON;;;;;N;;;;;
+19FB;KHMER SYMBOL DAP-MUOY ROC;So;0;ON;;;;;N;;;;;
+19FC;KHMER SYMBOL DAP-PII ROC;So;0;ON;;;;;N;;;;;
+19FD;KHMER SYMBOL DAP-BEI ROC;So;0;ON;;;;;N;;;;;
+19FE;KHMER SYMBOL DAP-BUON ROC;So;0;ON;;;;;N;;;;;
+19FF;KHMER SYMBOL DAP-PRAM ROC;So;0;ON;;;;;N;;;;;
+1A00;BUGINESE LETTER KA;Lo;0;L;;;;;N;;;;;
+1A01;BUGINESE LETTER GA;Lo;0;L;;;;;N;;;;;
+1A02;BUGINESE LETTER NGA;Lo;0;L;;;;;N;;;;;
+1A03;BUGINESE LETTER NGKA;Lo;0;L;;;;;N;;;;;
+1A04;BUGINESE LETTER PA;Lo;0;L;;;;;N;;;;;
+1A05;BUGINESE LETTER BA;Lo;0;L;;;;;N;;;;;
+1A06;BUGINESE LETTER MA;Lo;0;L;;;;;N;;;;;
+1A07;BUGINESE LETTER MPA;Lo;0;L;;;;;N;;;;;
+1A08;BUGINESE LETTER TA;Lo;0;L;;;;;N;;;;;
+1A09;BUGINESE LETTER DA;Lo;0;L;;;;;N;;;;;
+1A0A;BUGINESE LETTER NA;Lo;0;L;;;;;N;;;;;
+1A0B;BUGINESE LETTER NRA;Lo;0;L;;;;;N;;;;;
+1A0C;BUGINESE LETTER CA;Lo;0;L;;;;;N;;;;;
+1A0D;BUGINESE LETTER JA;Lo;0;L;;;;;N;;;;;
+1A0E;BUGINESE LETTER NYA;Lo;0;L;;;;;N;;;;;
+1A0F;BUGINESE LETTER NYCA;Lo;0;L;;;;;N;;;;;
+1A10;BUGINESE LETTER YA;Lo;0;L;;;;;N;;;;;
+1A11;BUGINESE LETTER RA;Lo;0;L;;;;;N;;;;;
+1A12;BUGINESE LETTER LA;Lo;0;L;;;;;N;;;;;
+1A13;BUGINESE LETTER VA;Lo;0;L;;;;;N;;;;;
+1A14;BUGINESE LETTER SA;Lo;0;L;;;;;N;;;;;
+1A15;BUGINESE LETTER A;Lo;0;L;;;;;N;;;;;
+1A16;BUGINESE LETTER HA;Lo;0;L;;;;;N;;;;;
+1A17;BUGINESE VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;;
+1A18;BUGINESE VOWEL SIGN U;Mn;220;NSM;;;;;N;;;;;
+1A19;BUGINESE VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+1A1A;BUGINESE VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+1A1B;BUGINESE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
+1A1E;BUGINESE PALLAWA;Po;0;L;;;;;N;;;;;
+1A1F;BUGINESE END OF SECTION;Po;0;L;;;;;N;;;;;
+1A20;TAI THAM LETTER HIGH KA;Lo;0;L;;;;;N;;;;;
+1A21;TAI THAM LETTER HIGH KHA;Lo;0;L;;;;;N;;;;;
+1A22;TAI THAM LETTER HIGH KXA;Lo;0;L;;;;;N;;;;;
+1A23;TAI THAM LETTER LOW KA;Lo;0;L;;;;;N;;;;;
+1A24;TAI THAM LETTER LOW KXA;Lo;0;L;;;;;N;;;;;
+1A25;TAI THAM LETTER LOW KHA;Lo;0;L;;;;;N;;;;;
+1A26;TAI THAM LETTER NGA;Lo;0;L;;;;;N;;;;;
+1A27;TAI THAM LETTER HIGH CA;Lo;0;L;;;;;N;;;;;
+1A28;TAI THAM LETTER HIGH CHA;Lo;0;L;;;;;N;;;;;
+1A29;TAI THAM LETTER LOW CA;Lo;0;L;;;;;N;;;;;
+1A2A;TAI THAM LETTER LOW SA;Lo;0;L;;;;;N;;;;;
+1A2B;TAI THAM LETTER LOW CHA;Lo;0;L;;;;;N;;;;;
+1A2C;TAI THAM LETTER NYA;Lo;0;L;;;;;N;;;;;
+1A2D;TAI THAM LETTER RATA;Lo;0;L;;;;;N;;;;;
+1A2E;TAI THAM LETTER HIGH RATHA;Lo;0;L;;;;;N;;;;;
+1A2F;TAI THAM LETTER DA;Lo;0;L;;;;;N;;;;;
+1A30;TAI THAM LETTER LOW RATHA;Lo;0;L;;;;;N;;;;;
+1A31;TAI THAM LETTER RANA;Lo;0;L;;;;;N;;;;;
+1A32;TAI THAM LETTER HIGH TA;Lo;0;L;;;;;N;;;;;
+1A33;TAI THAM LETTER HIGH THA;Lo;0;L;;;;;N;;;;;
+1A34;TAI THAM LETTER LOW TA;Lo;0;L;;;;;N;;;;;
+1A35;TAI THAM LETTER LOW THA;Lo;0;L;;;;;N;;;;;
+1A36;TAI THAM LETTER NA;Lo;0;L;;;;;N;;;;;
+1A37;TAI THAM LETTER BA;Lo;0;L;;;;;N;;;;;
+1A38;TAI THAM LETTER HIGH PA;Lo;0;L;;;;;N;;;;;
+1A39;TAI THAM LETTER HIGH PHA;Lo;0;L;;;;;N;;;;;
+1A3A;TAI THAM LETTER HIGH FA;Lo;0;L;;;;;N;;;;;
+1A3B;TAI THAM LETTER LOW PA;Lo;0;L;;;;;N;;;;;
+1A3C;TAI THAM LETTER LOW FA;Lo;0;L;;;;;N;;;;;
+1A3D;TAI THAM LETTER LOW PHA;Lo;0;L;;;;;N;;;;;
+1A3E;TAI THAM LETTER MA;Lo;0;L;;;;;N;;;;;
+1A3F;TAI THAM LETTER LOW YA;Lo;0;L;;;;;N;;;;;
+1A40;TAI THAM LETTER HIGH YA;Lo;0;L;;;;;N;;;;;
+1A41;TAI THAM LETTER RA;Lo;0;L;;;;;N;;;;;
+1A42;TAI THAM LETTER RUE;Lo;0;L;;;;;N;;;;;
+1A43;TAI THAM LETTER LA;Lo;0;L;;;;;N;;;;;
+1A44;TAI THAM LETTER LUE;Lo;0;L;;;;;N;;;;;
+1A45;TAI THAM LETTER WA;Lo;0;L;;;;;N;;;;;
+1A46;TAI THAM LETTER HIGH SHA;Lo;0;L;;;;;N;;;;;
+1A47;TAI THAM LETTER HIGH SSA;Lo;0;L;;;;;N;;;;;
+1A48;TAI THAM LETTER HIGH SA;Lo;0;L;;;;;N;;;;;
+1A49;TAI THAM LETTER HIGH HA;Lo;0;L;;;;;N;;;;;
+1A4A;TAI THAM LETTER LLA;Lo;0;L;;;;;N;;;;;
+1A4B;TAI THAM LETTER A;Lo;0;L;;;;;N;;;;;
+1A4C;TAI THAM LETTER LOW HA;Lo;0;L;;;;;N;;;;;
+1A4D;TAI THAM LETTER I;Lo;0;L;;;;;N;;;;;
+1A4E;TAI THAM LETTER II;Lo;0;L;;;;;N;;;;;
+1A4F;TAI THAM LETTER U;Lo;0;L;;;;;N;;;;;
+1A50;TAI THAM LETTER UU;Lo;0;L;;;;;N;;;;;
+1A51;TAI THAM LETTER EE;Lo;0;L;;;;;N;;;;;
+1A52;TAI THAM LETTER OO;Lo;0;L;;;;;N;;;;;
+1A53;TAI THAM LETTER LAE;Lo;0;L;;;;;N;;;;;
+1A54;TAI THAM LETTER GREAT SA;Lo;0;L;;;;;N;;;;;
+1A55;TAI THAM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;;
+1A56;TAI THAM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;;
+1A57;TAI THAM CONSONANT SIGN LA TANG LAI;Mc;0;L;;;;;N;;;;;
+1A58;TAI THAM SIGN MAI KANG LAI;Mn;0;NSM;;;;;N;;;;;
+1A59;TAI THAM CONSONANT SIGN FINAL NGA;Mn;0;NSM;;;;;N;;;;;
+1A5A;TAI THAM CONSONANT SIGN LOW PA;Mn;0;NSM;;;;;N;;;;;
+1A5B;TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA;Mn;0;NSM;;;;;N;;;;;
+1A5C;TAI THAM CONSONANT SIGN MA;Mn;0;NSM;;;;;N;;;;;
+1A5D;TAI THAM CONSONANT SIGN BA;Mn;0;NSM;;;;;N;;;;;
+1A5E;TAI THAM CONSONANT SIGN SA;Mn;0;NSM;;;;;N;;;;;
+1A60;TAI THAM SIGN SAKOT;Mn;9;NSM;;;;;N;;;;;
+1A61;TAI THAM VOWEL SIGN A;Mc;0;L;;;;;N;;;;;
+1A62;TAI THAM VOWEL SIGN MAI SAT;Mn;0;NSM;;;;;N;;;;;
+1A63;TAI THAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+1A64;TAI THAM VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;;
+1A65;TAI THAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+1A66;TAI THAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+1A67;TAI THAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
+1A68;TAI THAM VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;;
+1A69;TAI THAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+1A6A;TAI THAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+1A6B;TAI THAM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+1A6C;TAI THAM VOWEL SIGN OA BELOW;Mn;0;NSM;;;;;N;;;;;
+1A6D;TAI THAM VOWEL SIGN OY;Mc;0;L;;;;;N;;;;;
+1A6E;TAI THAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+1A6F;TAI THAM VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
+1A70;TAI THAM VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
+1A71;TAI THAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+1A72;TAI THAM VOWEL SIGN THAM AI;Mc;0;L;;;;;N;;;;;
+1A73;TAI THAM VOWEL SIGN OA ABOVE;Mn;0;NSM;;;;;N;;;;;
+1A74;TAI THAM SIGN MAI KANG;Mn;0;NSM;;;;;N;;;;;
+1A75;TAI THAM SIGN TONE-1;Mn;230;NSM;;;;;N;;;;;
+1A76;TAI THAM SIGN TONE-2;Mn;230;NSM;;;;;N;;;;;
+1A77;TAI THAM SIGN KHUEN TONE-3;Mn;230;NSM;;;;;N;;;;;
+1A78;TAI THAM SIGN KHUEN TONE-4;Mn;230;NSM;;;;;N;;;;;
+1A79;TAI THAM SIGN KHUEN TONE-5;Mn;230;NSM;;;;;N;;;;;
+1A7A;TAI THAM SIGN RA HAAM;Mn;230;NSM;;;;;N;;;;;
+1A7B;TAI THAM SIGN MAI SAM;Mn;230;NSM;;;;;N;;;;;
+1A7C;TAI THAM SIGN KHUEN-LUE KARAN;Mn;230;NSM;;;;;N;;;;;
+1A7F;TAI THAM COMBINING CRYPTOGRAMMIC DOT;Mn;220;NSM;;;;;N;;;;;
+1A80;TAI THAM HORA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1A81;TAI THAM HORA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1A82;TAI THAM HORA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1A83;TAI THAM HORA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1A84;TAI THAM HORA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1A85;TAI THAM HORA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1A86;TAI THAM HORA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1A87;TAI THAM HORA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1A88;TAI THAM HORA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1A89;TAI THAM HORA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1A90;TAI THAM THAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1A91;TAI THAM THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1A92;TAI THAM THAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1A93;TAI THAM THAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1A94;TAI THAM THAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1A95;TAI THAM THAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1A96;TAI THAM THAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1A97;TAI THAM THAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1A98;TAI THAM THAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1A99;TAI THAM THAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1AA0;TAI THAM SIGN WIANG;Po;0;L;;;;;N;;;;;
+1AA1;TAI THAM SIGN WIANGWAAK;Po;0;L;;;;;N;;;;;
+1AA2;TAI THAM SIGN SAWAN;Po;0;L;;;;;N;;;;;
+1AA3;TAI THAM SIGN KEOW;Po;0;L;;;;;N;;;;;
+1AA4;TAI THAM SIGN HOY;Po;0;L;;;;;N;;;;;
+1AA5;TAI THAM SIGN DOKMAI;Po;0;L;;;;;N;;;;;
+1AA6;TAI THAM SIGN REVERSED ROTATED RANA;Po;0;L;;;;;N;;;;;
+1AA7;TAI THAM SIGN MAI YAMOK;Lm;0;L;;;;;N;;;;;
+1AA8;TAI THAM SIGN KAAN;Po;0;L;;;;;N;;;;;
+1AA9;TAI THAM SIGN KAANKUU;Po;0;L;;;;;N;;;;;
+1AAA;TAI THAM SIGN SATKAAN;Po;0;L;;;;;N;;;;;
+1AAB;TAI THAM SIGN SATKAANKUU;Po;0;L;;;;;N;;;;;
+1AAC;TAI THAM SIGN HANG;Po;0;L;;;;;N;;;;;
+1AAD;TAI THAM SIGN CAANG;Po;0;L;;;;;N;;;;;
+1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;;
+1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;;
+1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;;
+1B03;BALINESE SIGN SURANG;Mn;0;NSM;;;;;N;;;;;
+1B04;BALINESE SIGN BISAH;Mc;0;L;;;;;N;;;;;
+1B05;BALINESE LETTER AKARA;Lo;0;L;;;;;N;;;;;
+1B06;BALINESE LETTER AKARA TEDUNG;Lo;0;L;1B05 1B35;;;;N;;;;;
+1B07;BALINESE LETTER IKARA;Lo;0;L;;;;;N;;;;;
+1B08;BALINESE LETTER IKARA TEDUNG;Lo;0;L;1B07 1B35;;;;N;;;;;
+1B09;BALINESE LETTER UKARA;Lo;0;L;;;;;N;;;;;
+1B0A;BALINESE LETTER UKARA TEDUNG;Lo;0;L;1B09 1B35;;;;N;;;;;
+1B0B;BALINESE LETTER RA REPA;Lo;0;L;;;;;N;;;;;
+1B0C;BALINESE LETTER RA REPA TEDUNG;Lo;0;L;1B0B 1B35;;;;N;;;;;
+1B0D;BALINESE LETTER LA LENGA;Lo;0;L;;;;;N;;;;;
+1B0E;BALINESE LETTER LA LENGA TEDUNG;Lo;0;L;1B0D 1B35;;;;N;;;;;
+1B0F;BALINESE LETTER EKARA;Lo;0;L;;;;;N;;;;;
+1B10;BALINESE LETTER AIKARA;Lo;0;L;;;;;N;;;;;
+1B11;BALINESE LETTER OKARA;Lo;0;L;;;;;N;;;;;
+1B12;BALINESE LETTER OKARA TEDUNG;Lo;0;L;1B11 1B35;;;;N;;;;;
+1B13;BALINESE LETTER KA;Lo;0;L;;;;;N;;;;;
+1B14;BALINESE LETTER KA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+1B15;BALINESE LETTER GA;Lo;0;L;;;;;N;;;;;
+1B16;BALINESE LETTER GA GORA;Lo;0;L;;;;;N;;;;;
+1B17;BALINESE LETTER NGA;Lo;0;L;;;;;N;;;;;
+1B18;BALINESE LETTER CA;Lo;0;L;;;;;N;;;;;
+1B19;BALINESE LETTER CA LACA;Lo;0;L;;;;;N;;;;;
+1B1A;BALINESE LETTER JA;Lo;0;L;;;;;N;;;;;
+1B1B;BALINESE LETTER JA JERA;Lo;0;L;;;;;N;;;;;
+1B1C;BALINESE LETTER NYA;Lo;0;L;;;;;N;;;;;
+1B1D;BALINESE LETTER TA LATIK;Lo;0;L;;;;;N;;;;;
+1B1E;BALINESE LETTER TA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+1B1F;BALINESE LETTER DA MURDA ALPAPRANA;Lo;0;L;;;;;N;;;;;
+1B20;BALINESE LETTER DA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+1B21;BALINESE LETTER NA RAMBAT;Lo;0;L;;;;;N;;;;;
+1B22;BALINESE LETTER TA;Lo;0;L;;;;;N;;;;;
+1B23;BALINESE LETTER TA TAWA;Lo;0;L;;;;;N;;;;;
+1B24;BALINESE LETTER DA;Lo;0;L;;;;;N;;;;;
+1B25;BALINESE LETTER DA MADU;Lo;0;L;;;;;N;;;;;
+1B26;BALINESE LETTER NA;Lo;0;L;;;;;N;;;;;
+1B27;BALINESE LETTER PA;Lo;0;L;;;;;N;;;;;
+1B28;BALINESE LETTER PA KAPAL;Lo;0;L;;;;;N;;;;;
+1B29;BALINESE LETTER BA;Lo;0;L;;;;;N;;;;;
+1B2A;BALINESE LETTER BA KEMBANG;Lo;0;L;;;;;N;;;;;
+1B2B;BALINESE LETTER MA;Lo;0;L;;;;;N;;;;;
+1B2C;BALINESE LETTER YA;Lo;0;L;;;;;N;;;;;
+1B2D;BALINESE LETTER RA;Lo;0;L;;;;;N;;;;;
+1B2E;BALINESE LETTER LA;Lo;0;L;;;;;N;;;;;
+1B2F;BALINESE LETTER WA;Lo;0;L;;;;;N;;;;;
+1B30;BALINESE LETTER SA SAGA;Lo;0;L;;;;;N;;;;;
+1B31;BALINESE LETTER SA SAPA;Lo;0;L;;;;;N;;;;;
+1B32;BALINESE LETTER SA;Lo;0;L;;;;;N;;;;;
+1B33;BALINESE LETTER HA;Lo;0;L;;;;;N;;;;;
+1B34;BALINESE SIGN REREKAN;Mn;7;NSM;;;;;N;;;;;
+1B35;BALINESE VOWEL SIGN TEDUNG;Mc;0;L;;;;;N;;;;;
+1B36;BALINESE VOWEL SIGN ULU;Mn;0;NSM;;;;;N;;;;;
+1B37;BALINESE VOWEL SIGN ULU SARI;Mn;0;NSM;;;;;N;;;;;
+1B38;BALINESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;;
+1B39;BALINESE VOWEL SIGN SUKU ILUT;Mn;0;NSM;;;;;N;;;;;
+1B3A;BALINESE VOWEL SIGN RA REPA;Mn;0;NSM;;;;;N;;;;;
+1B3B;BALINESE VOWEL SIGN RA REPA TEDUNG;Mc;0;L;1B3A 1B35;;;;N;;;;;
+1B3C;BALINESE VOWEL SIGN LA LENGA;Mn;0;NSM;;;;;N;;;;;
+1B3D;BALINESE VOWEL SIGN LA LENGA TEDUNG;Mc;0;L;1B3C 1B35;;;;N;;;;;
+1B3E;BALINESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;;
+1B3F;BALINESE VOWEL SIGN TALING REPA;Mc;0;L;;;;;N;;;;;
+1B40;BALINESE VOWEL SIGN TALING TEDUNG;Mc;0;L;1B3E 1B35;;;;N;;;;;
+1B41;BALINESE VOWEL SIGN TALING REPA TEDUNG;Mc;0;L;1B3F 1B35;;;;N;;;;;
+1B42;BALINESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;;
+1B43;BALINESE VOWEL SIGN PEPET TEDUNG;Mc;0;L;1B42 1B35;;;;N;;;;;
+1B44;BALINESE ADEG ADEG;Mc;9;L;;;;;N;;;;;
+1B45;BALINESE LETTER KAF SASAK;Lo;0;L;;;;;N;;;;;
+1B46;BALINESE LETTER KHOT SASAK;Lo;0;L;;;;;N;;;;;
+1B47;BALINESE LETTER TZIR SASAK;Lo;0;L;;;;;N;;;;;
+1B48;BALINESE LETTER EF SASAK;Lo;0;L;;;;;N;;;;;
+1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;;
+1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;;
+1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;;
+1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1B53;BALINESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1B54;BALINESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1B55;BALINESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1B56;BALINESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1B57;BALINESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1B58;BALINESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1B59;BALINESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1B5A;BALINESE PANTI;Po;0;L;;;;;N;;;;;
+1B5B;BALINESE PAMADA;Po;0;L;;;;;N;;;;;
+1B5C;BALINESE WINDU;Po;0;L;;;;;N;;;;;
+1B5D;BALINESE CARIK PAMUNGKAH;Po;0;L;;;;;N;;;;;
+1B5E;BALINESE CARIK SIKI;Po;0;L;;;;;N;;;;;
+1B5F;BALINESE CARIK PAREREN;Po;0;L;;;;;N;;;;;
+1B60;BALINESE PAMENENG;Po;0;L;;;;;N;;;;;
+1B61;BALINESE MUSICAL SYMBOL DONG;So;0;L;;;;;N;;;;;
+1B62;BALINESE MUSICAL SYMBOL DENG;So;0;L;;;;;N;;;;;
+1B63;BALINESE MUSICAL SYMBOL DUNG;So;0;L;;;;;N;;;;;
+1B64;BALINESE MUSICAL SYMBOL DANG;So;0;L;;;;;N;;;;;
+1B65;BALINESE MUSICAL SYMBOL DANG SURANG;So;0;L;;;;;N;;;;;
+1B66;BALINESE MUSICAL SYMBOL DING;So;0;L;;;;;N;;;;;
+1B67;BALINESE MUSICAL SYMBOL DAENG;So;0;L;;;;;N;;;;;
+1B68;BALINESE MUSICAL SYMBOL DEUNG;So;0;L;;;;;N;;;;;
+1B69;BALINESE MUSICAL SYMBOL DAING;So;0;L;;;;;N;;;;;
+1B6A;BALINESE MUSICAL SYMBOL DANG GEDE;So;0;L;;;;;N;;;;;
+1B6B;BALINESE MUSICAL SYMBOL COMBINING TEGEH;Mn;230;NSM;;;;;N;;;;;
+1B6C;BALINESE MUSICAL SYMBOL COMBINING ENDEP;Mn;220;NSM;;;;;N;;;;;
+1B6D;BALINESE MUSICAL SYMBOL COMBINING KEMPUL;Mn;230;NSM;;;;;N;;;;;
+1B6E;BALINESE MUSICAL SYMBOL COMBINING KEMPLI;Mn;230;NSM;;;;;N;;;;;
+1B6F;BALINESE MUSICAL SYMBOL COMBINING JEGOGAN;Mn;230;NSM;;;;;N;;;;;
+1B70;BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;;
+1B71;BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;;
+1B72;BALINESE MUSICAL SYMBOL COMBINING BENDE;Mn;230;NSM;;;;;N;;;;;
+1B73;BALINESE MUSICAL SYMBOL COMBINING GONG;Mn;230;NSM;;;;;N;;;;;
+1B74;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG;So;0;L;;;;;N;;;;;
+1B75;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG;So;0;L;;;;;N;;;;;
+1B76;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK;So;0;L;;;;;N;;;;;
+1B77;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK;So;0;L;;;;;N;;;;;
+1B78;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG;So;0;L;;;;;N;;;;;
+1B79;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG;So;0;L;;;;;N;;;;;
+1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;;
+1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;;
+1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;;
+1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;;
+1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;;
+1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;;
+1B83;SUNDANESE LETTER A;Lo;0;L;;;;;N;;;;;
+1B84;SUNDANESE LETTER I;Lo;0;L;;;;;N;;;;;
+1B85;SUNDANESE LETTER U;Lo;0;L;;;;;N;;;;;
+1B86;SUNDANESE LETTER AE;Lo;0;L;;;;;N;;;;;
+1B87;SUNDANESE LETTER O;Lo;0;L;;;;;N;;;;;
+1B88;SUNDANESE LETTER E;Lo;0;L;;;;;N;;;;;
+1B89;SUNDANESE LETTER EU;Lo;0;L;;;;;N;;;;;
+1B8A;SUNDANESE LETTER KA;Lo;0;L;;;;;N;;;;;
+1B8B;SUNDANESE LETTER QA;Lo;0;L;;;;;N;;;;;
+1B8C;SUNDANESE LETTER GA;Lo;0;L;;;;;N;;;;;
+1B8D;SUNDANESE LETTER NGA;Lo;0;L;;;;;N;;;;;
+1B8E;SUNDANESE LETTER CA;Lo;0;L;;;;;N;;;;;
+1B8F;SUNDANESE LETTER JA;Lo;0;L;;;;;N;;;;;
+1B90;SUNDANESE LETTER ZA;Lo;0;L;;;;;N;;;;;
+1B91;SUNDANESE LETTER NYA;Lo;0;L;;;;;N;;;;;
+1B92;SUNDANESE LETTER TA;Lo;0;L;;;;;N;;;;;
+1B93;SUNDANESE LETTER DA;Lo;0;L;;;;;N;;;;;
+1B94;SUNDANESE LETTER NA;Lo;0;L;;;;;N;;;;;
+1B95;SUNDANESE LETTER PA;Lo;0;L;;;;;N;;;;;
+1B96;SUNDANESE LETTER FA;Lo;0;L;;;;;N;;;;;
+1B97;SUNDANESE LETTER VA;Lo;0;L;;;;;N;;;;;
+1B98;SUNDANESE LETTER BA;Lo;0;L;;;;;N;;;;;
+1B99;SUNDANESE LETTER MA;Lo;0;L;;;;;N;;;;;
+1B9A;SUNDANESE LETTER YA;Lo;0;L;;;;;N;;;;;
+1B9B;SUNDANESE LETTER RA;Lo;0;L;;;;;N;;;;;
+1B9C;SUNDANESE LETTER LA;Lo;0;L;;;;;N;;;;;
+1B9D;SUNDANESE LETTER WA;Lo;0;L;;;;;N;;;;;
+1B9E;SUNDANESE LETTER SA;Lo;0;L;;;;;N;;;;;
+1B9F;SUNDANESE LETTER XA;Lo;0;L;;;;;N;;;;;
+1BA0;SUNDANESE LETTER HA;Lo;0;L;;;;;N;;;;;
+1BA1;SUNDANESE CONSONANT SIGN PAMINGKAL;Mc;0;L;;;;;N;;;;;
+1BA2;SUNDANESE CONSONANT SIGN PANYAKRA;Mn;0;NSM;;;;;N;;;;;
+1BA3;SUNDANESE CONSONANT SIGN PANYIKU;Mn;0;NSM;;;;;N;;;;;
+1BA4;SUNDANESE VOWEL SIGN PANGHULU;Mn;0;NSM;;;;;N;;;;;
+1BA5;SUNDANESE VOWEL SIGN PANYUKU;Mn;0;NSM;;;;;N;;;;;
+1BA6;SUNDANESE VOWEL SIGN PANAELAENG;Mc;0;L;;;;;N;;;;;
+1BA7;SUNDANESE VOWEL SIGN PANOLONG;Mc;0;L;;;;;N;;;;;
+1BA8;SUNDANESE VOWEL SIGN PAMEPET;Mn;0;NSM;;;;;N;;;;;
+1BA9;SUNDANESE VOWEL SIGN PANEULEUNG;Mn;0;NSM;;;;;N;;;;;
+1BAA;SUNDANESE SIGN PAMAAEH;Mc;9;L;;;;;N;;;;;
+1BAE;SUNDANESE LETTER KHA;Lo;0;L;;;;;N;;;;;
+1BAF;SUNDANESE LETTER SYA;Lo;0;L;;;;;N;;;;;
+1BB0;SUNDANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1BB1;SUNDANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1BB2;SUNDANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1BB3;SUNDANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1BB4;SUNDANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1BB5;SUNDANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1BB6;SUNDANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;;
+1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;;
+1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;;
+1C03;LEPCHA LETTER GA;Lo;0;L;;;;;N;;;;;
+1C04;LEPCHA LETTER GLA;Lo;0;L;;;;;N;;;;;
+1C05;LEPCHA LETTER NGA;Lo;0;L;;;;;N;;;;;
+1C06;LEPCHA LETTER CA;Lo;0;L;;;;;N;;;;;
+1C07;LEPCHA LETTER CHA;Lo;0;L;;;;;N;;;;;
+1C08;LEPCHA LETTER JA;Lo;0;L;;;;;N;;;;;
+1C09;LEPCHA LETTER NYA;Lo;0;L;;;;;N;;;;;
+1C0A;LEPCHA LETTER TA;Lo;0;L;;;;;N;;;;;
+1C0B;LEPCHA LETTER THA;Lo;0;L;;;;;N;;;;;
+1C0C;LEPCHA LETTER DA;Lo;0;L;;;;;N;;;;;
+1C0D;LEPCHA LETTER NA;Lo;0;L;;;;;N;;;;;
+1C0E;LEPCHA LETTER PA;Lo;0;L;;;;;N;;;;;
+1C0F;LEPCHA LETTER PLA;Lo;0;L;;;;;N;;;;;
+1C10;LEPCHA LETTER PHA;Lo;0;L;;;;;N;;;;;
+1C11;LEPCHA LETTER FA;Lo;0;L;;;;;N;;;;;
+1C12;LEPCHA LETTER FLA;Lo;0;L;;;;;N;;;;;
+1C13;LEPCHA LETTER BA;Lo;0;L;;;;;N;;;;;
+1C14;LEPCHA LETTER BLA;Lo;0;L;;;;;N;;;;;
+1C15;LEPCHA LETTER MA;Lo;0;L;;;;;N;;;;;
+1C16;LEPCHA LETTER MLA;Lo;0;L;;;;;N;;;;;
+1C17;LEPCHA LETTER TSA;Lo;0;L;;;;;N;;;;;
+1C18;LEPCHA LETTER TSHA;Lo;0;L;;;;;N;;;;;
+1C19;LEPCHA LETTER DZA;Lo;0;L;;;;;N;;;;;
+1C1A;LEPCHA LETTER YA;Lo;0;L;;;;;N;;;;;
+1C1B;LEPCHA LETTER RA;Lo;0;L;;;;;N;;;;;
+1C1C;LEPCHA LETTER LA;Lo;0;L;;;;;N;;;;;
+1C1D;LEPCHA LETTER HA;Lo;0;L;;;;;N;;;;;
+1C1E;LEPCHA LETTER HLA;Lo;0;L;;;;;N;;;;;
+1C1F;LEPCHA LETTER VA;Lo;0;L;;;;;N;;;;;
+1C20;LEPCHA LETTER SA;Lo;0;L;;;;;N;;;;;
+1C21;LEPCHA LETTER SHA;Lo;0;L;;;;;N;;;;;
+1C22;LEPCHA LETTER WA;Lo;0;L;;;;;N;;;;;
+1C23;LEPCHA LETTER A;Lo;0;L;;;;;N;;;;;
+1C24;LEPCHA SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;;
+1C25;LEPCHA SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;;
+1C26;LEPCHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+1C27;LEPCHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+1C28;LEPCHA VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+1C29;LEPCHA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
+1C2A;LEPCHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
+1C2B;LEPCHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
+1C2C;LEPCHA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+1C2D;LEPCHA CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;;
+1C2E;LEPCHA CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;;
+1C2F;LEPCHA CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;;
+1C30;LEPCHA CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;;
+1C31;LEPCHA CONSONANT SIGN P;Mn;0;NSM;;;;;N;;;;;
+1C32;LEPCHA CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;;
+1C33;LEPCHA CONSONANT SIGN T;Mn;0;NSM;;;;;N;;;;;
+1C34;LEPCHA CONSONANT SIGN NYIN-DO;Mc;0;L;;;;;N;;;;;
+1C35;LEPCHA CONSONANT SIGN KANG;Mc;0;L;;;;;N;;;;;
+1C36;LEPCHA SIGN RAN;Mn;0;NSM;;;;;N;;;;;
+1C37;LEPCHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+1C3B;LEPCHA PUNCTUATION TA-ROL;Po;0;L;;;;;N;;;;;
+1C3C;LEPCHA PUNCTUATION NYET THYOOM TA-ROL;Po;0;L;;;;;N;;;;;
+1C3D;LEPCHA PUNCTUATION CER-WA;Po;0;L;;;;;N;;;;;
+1C3E;LEPCHA PUNCTUATION TSHOOK CER-WA;Po;0;L;;;;;N;;;;;
+1C3F;LEPCHA PUNCTUATION TSHOOK;Po;0;L;;;;;N;;;;;
+1C40;LEPCHA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1C41;LEPCHA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1C42;LEPCHA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1C43;LEPCHA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1C44;LEPCHA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1C45;LEPCHA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1C46;LEPCHA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1C47;LEPCHA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1C48;LEPCHA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1C49;LEPCHA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1C4D;LEPCHA LETTER TTA;Lo;0;L;;;;;N;;;;;
+1C4E;LEPCHA LETTER TTHA;Lo;0;L;;;;;N;;;;;
+1C4F;LEPCHA LETTER DDA;Lo;0;L;;;;;N;;;;;
+1C50;OL CHIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+1C51;OL CHIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+1C52;OL CHIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+1C53;OL CHIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+1C54;OL CHIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+1C55;OL CHIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+1C56;OL CHIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+1C57;OL CHIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+1C58;OL CHIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+1C59;OL CHIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1C5A;OL CHIKI LETTER LA;Lo;0;L;;;;;N;;;;;
+1C5B;OL CHIKI LETTER AT;Lo;0;L;;;;;N;;;;;
+1C5C;OL CHIKI LETTER AG;Lo;0;L;;;;;N;;;;;
+1C5D;OL CHIKI LETTER ANG;Lo;0;L;;;;;N;;;;;
+1C5E;OL CHIKI LETTER AL;Lo;0;L;;;;;N;;;;;
+1C5F;OL CHIKI LETTER LAA;Lo;0;L;;;;;N;;;;;
+1C60;OL CHIKI LETTER AAK;Lo;0;L;;;;;N;;;;;
+1C61;OL CHIKI LETTER AAJ;Lo;0;L;;;;;N;;;;;
+1C62;OL CHIKI LETTER AAM;Lo;0;L;;;;;N;;;;;
+1C63;OL CHIKI LETTER AAW;Lo;0;L;;;;;N;;;;;
+1C64;OL CHIKI LETTER LI;Lo;0;L;;;;;N;;;;;
+1C65;OL CHIKI LETTER IS;Lo;0;L;;;;;N;;;;;
+1C66;OL CHIKI LETTER IH;Lo;0;L;;;;;N;;;;;
+1C67;OL CHIKI LETTER INY;Lo;0;L;;;;;N;;;;;
+1C68;OL CHIKI LETTER IR;Lo;0;L;;;;;N;;;;;
+1C69;OL CHIKI LETTER LU;Lo;0;L;;;;;N;;;;;
+1C6A;OL CHIKI LETTER UC;Lo;0;L;;;;;N;;;;;
+1C6B;OL CHIKI LETTER UD;Lo;0;L;;;;;N;;;;;
+1C6C;OL CHIKI LETTER UNN;Lo;0;L;;;;;N;;;;;
+1C6D;OL CHIKI LETTER UY;Lo;0;L;;;;;N;;;;;
+1C6E;OL CHIKI LETTER LE;Lo;0;L;;;;;N;;;;;
+1C6F;OL CHIKI LETTER EP;Lo;0;L;;;;;N;;;;;
+1C70;OL CHIKI LETTER EDD;Lo;0;L;;;;;N;;;;;
+1C71;OL CHIKI LETTER EN;Lo;0;L;;;;;N;;;;;
+1C72;OL CHIKI LETTER ERR;Lo;0;L;;;;;N;;;;;
+1C73;OL CHIKI LETTER LO;Lo;0;L;;;;;N;;;;;
+1C74;OL CHIKI LETTER OTT;Lo;0;L;;;;;N;;;;;
+1C75;OL CHIKI LETTER OB;Lo;0;L;;;;;N;;;;;
+1C76;OL CHIKI LETTER OV;Lo;0;L;;;;;N;;;;;
+1C77;OL CHIKI LETTER OH;Lo;0;L;;;;;N;;;;;
+1C78;OL CHIKI MU TTUDDAG;Lm;0;L;;;;;N;;;;;
+1C79;OL CHIKI GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;;
+1C7A;OL CHIKI MU-GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;;
+1C7B;OL CHIKI RELAA;Lm;0;L;;;;;N;;;;;
+1C7C;OL CHIKI PHAARKAA;Lm;0;L;;;;;N;;;;;
+1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;;
+1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;;
+1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;;
+1CD0;VEDIC TONE KARSHANA;Mn;230;NSM;;;;;N;;;;;
+1CD1;VEDIC TONE SHARA;Mn;230;NSM;;;;;N;;;;;
+1CD2;VEDIC TONE PRENKHA;Mn;230;NSM;;;;;N;;;;;
+1CD3;VEDIC SIGN NIHSHVASA;Po;0;L;;;;;N;;;;;
+1CD4;VEDIC SIGN YAJURVEDIC MIDLINE SVARITA;Mn;1;NSM;;;;;N;;;;;
+1CD5;VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;;
+1CD6;VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;;
+1CD7;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;;
+1CD8;VEDIC TONE CANDRA BELOW;Mn;220;NSM;;;;;N;;;;;
+1CD9;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER;Mn;220;NSM;;;;;N;;;;;
+1CDA;VEDIC TONE DOUBLE SVARITA;Mn;230;NSM;;;;;N;;;;;
+1CDB;VEDIC TONE TRIPLE SVARITA;Mn;230;NSM;;;;;N;;;;;
+1CDC;VEDIC TONE KATHAKA ANUDATTA;Mn;220;NSM;;;;;N;;;;;
+1CDD;VEDIC TONE DOT BELOW;Mn;220;NSM;;;;;N;;;;;
+1CDE;VEDIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
+1CDF;VEDIC TONE THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
+1CE0;VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA;Mn;230;NSM;;;;;N;;;;;
+1CE1;VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA;Mc;0;L;;;;;N;;;;;
+1CE2;VEDIC SIGN VISARGA SVARITA;Mn;1;NSM;;;;;N;;;;;
+1CE3;VEDIC SIGN VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;;
+1CE4;VEDIC SIGN REVERSED VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;;
+1CE5;VEDIC SIGN VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;;
+1CE6;VEDIC SIGN REVERSED VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;;
+1CE7;VEDIC SIGN VISARGA UDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;;
+1CE8;VEDIC SIGN VISARGA ANUDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;;
+1CE9;VEDIC SIGN ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;;
+1CEA;VEDIC SIGN ANUSVARA BAHIRGOMUKHA;Lo;0;L;;;;;N;;;;;
+1CEB;VEDIC SIGN ANUSVARA VAMAGOMUKHA;Lo;0;L;;;;;N;;;;;
+1CEC;VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL;Lo;0;L;;;;;N;;;;;
+1CED;VEDIC SIGN TIRYAK;Mn;220;NSM;;;;;N;;;;;
+1CEE;VEDIC SIGN HEXIFORM LONG ANUSVARA;Lo;0;L;;;;;N;;;;;
+1CEF;VEDIC SIGN LONG ANUSVARA;Lo;0;L;;;;;N;;;;;
+1CF0;VEDIC SIGN RTHANG LONG ANUSVARA;Lo;0;L;;;;;N;;;;;
+1CF1;VEDIC SIGN ANUSVARA UBHAYATO MUKHA;Lo;0;L;;;;;N;;;;;
+1CF2;VEDIC SIGN ARDHAVISARGA;Mc;0;L;;;;;N;;;;;
+1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;;
+1D01;LATIN LETTER SMALL CAPITAL AE;Ll;0;L;;;;;N;;;;;
+1D02;LATIN SMALL LETTER TURNED AE;Ll;0;L;;;;;N;;;;;
+1D03;LATIN LETTER SMALL CAPITAL BARRED B;Ll;0;L;;;;;N;;;;;
+1D04;LATIN LETTER SMALL CAPITAL C;Ll;0;L;;;;;N;;;;;
+1D05;LATIN LETTER SMALL CAPITAL D;Ll;0;L;;;;;N;;;;;
+1D06;LATIN LETTER SMALL CAPITAL ETH;Ll;0;L;;;;;N;;;;;
+1D07;LATIN LETTER SMALL CAPITAL E;Ll;0;L;;;;;N;;;;;
+1D08;LATIN SMALL LETTER TURNED OPEN E;Ll;0;L;;;;;N;;;;;
+1D09;LATIN SMALL LETTER TURNED I;Ll;0;L;;;;;N;;;;;
+1D0A;LATIN LETTER SMALL CAPITAL J;Ll;0;L;;;;;N;;;;;
+1D0B;LATIN LETTER SMALL CAPITAL K;Ll;0;L;;;;;N;;;;;
+1D0C;LATIN LETTER SMALL CAPITAL L WITH STROKE;Ll;0;L;;;;;N;;;;;
+1D0D;LATIN LETTER SMALL CAPITAL M;Ll;0;L;;;;;N;;;;;
+1D0E;LATIN LETTER SMALL CAPITAL REVERSED N;Ll;0;L;;;;;N;;;;;
+1D0F;LATIN LETTER SMALL CAPITAL O;Ll;0;L;;;;;N;;;;;
+1D10;LATIN LETTER SMALL CAPITAL OPEN O;Ll;0;L;;;;;N;;;;;
+1D11;LATIN SMALL LETTER SIDEWAYS O;Ll;0;L;;;;;N;;;;;
+1D12;LATIN SMALL LETTER SIDEWAYS OPEN O;Ll;0;L;;;;;N;;;;;
+1D13;LATIN SMALL LETTER SIDEWAYS O WITH STROKE;Ll;0;L;;;;;N;;;;;
+1D14;LATIN SMALL LETTER TURNED OE;Ll;0;L;;;;;N;;;;;
+1D15;LATIN LETTER SMALL CAPITAL OU;Ll;0;L;;;;;N;;;;;
+1D16;LATIN SMALL LETTER TOP HALF O;Ll;0;L;;;;;N;;;;;
+1D17;LATIN SMALL LETTER BOTTOM HALF O;Ll;0;L;;;;;N;;;;;
+1D18;LATIN LETTER SMALL CAPITAL P;Ll;0;L;;;;;N;;;;;
+1D19;LATIN LETTER SMALL CAPITAL REVERSED R;Ll;0;L;;;;;N;;;;;
+1D1A;LATIN LETTER SMALL CAPITAL TURNED R;Ll;0;L;;;;;N;;;;;
+1D1B;LATIN LETTER SMALL CAPITAL T;Ll;0;L;;;;;N;;;;;
+1D1C;LATIN LETTER SMALL CAPITAL U;Ll;0;L;;;;;N;;;;;
+1D1D;LATIN SMALL LETTER SIDEWAYS U;Ll;0;L;;;;;N;;;;;
+1D1E;LATIN SMALL LETTER SIDEWAYS DIAERESIZED U;Ll;0;L;;;;;N;;;;;
+1D1F;LATIN SMALL LETTER SIDEWAYS TURNED M;Ll;0;L;;;;;N;;;;;
+1D20;LATIN LETTER SMALL CAPITAL V;Ll;0;L;;;;;N;;;;;
+1D21;LATIN LETTER SMALL CAPITAL W;Ll;0;L;;;;;N;;;;;
+1D22;LATIN LETTER SMALL CAPITAL Z;Ll;0;L;;;;;N;;;;;
+1D23;LATIN LETTER SMALL CAPITAL EZH;Ll;0;L;;;;;N;;;;;
+1D24;LATIN LETTER VOICED LARYNGEAL SPIRANT;Ll;0;L;;;;;N;;;;;
+1D25;LATIN LETTER AIN;Ll;0;L;;;;;N;;;;;
+1D26;GREEK LETTER SMALL CAPITAL GAMMA;Ll;0;L;;;;;N;;;;;
+1D27;GREEK LETTER SMALL CAPITAL LAMDA;Ll;0;L;;;;;N;;;;;
+1D28;GREEK LETTER SMALL CAPITAL PI;Ll;0;L;;;;;N;;;;;
+1D29;GREEK LETTER SMALL CAPITAL RHO;Ll;0;L;;;;;N;;;;;
+1D2A;GREEK LETTER SMALL CAPITAL PSI;Ll;0;L;;;;;N;;;;;
+1D2B;CYRILLIC LETTER SMALL CAPITAL EL;Ll;0;L;;;;;N;;;;;
+1D2C;MODIFIER LETTER CAPITAL A;Lm;0;L;<super> 0041;;;;N;;;;;
+1D2D;MODIFIER LETTER CAPITAL AE;Lm;0;L;<super> 00C6;;;;N;;;;;
+1D2E;MODIFIER LETTER CAPITAL B;Lm;0;L;<super> 0042;;;;N;;;;;
+1D2F;MODIFIER LETTER CAPITAL BARRED B;Lm;0;L;;;;;N;;;;;
+1D30;MODIFIER LETTER CAPITAL D;Lm;0;L;<super> 0044;;;;N;;;;;
+1D31;MODIFIER LETTER CAPITAL E;Lm;0;L;<super> 0045;;;;N;;;;;
+1D32;MODIFIER LETTER CAPITAL REVERSED E;Lm;0;L;<super> 018E;;;;N;;;;;
+1D33;MODIFIER LETTER CAPITAL G;Lm;0;L;<super> 0047;;;;N;;;;;
+1D34;MODIFIER LETTER CAPITAL H;Lm;0;L;<super> 0048;;;;N;;;;;
+1D35;MODIFIER LETTER CAPITAL I;Lm;0;L;<super> 0049;;;;N;;;;;
+1D36;MODIFIER LETTER CAPITAL J;Lm;0;L;<super> 004A;;;;N;;;;;
+1D37;MODIFIER LETTER CAPITAL K;Lm;0;L;<super> 004B;;;;N;;;;;
+1D38;MODIFIER LETTER CAPITAL L;Lm;0;L;<super> 004C;;;;N;;;;;
+1D39;MODIFIER LETTER CAPITAL M;Lm;0;L;<super> 004D;;;;N;;;;;
+1D3A;MODIFIER LETTER CAPITAL N;Lm;0;L;<super> 004E;;;;N;;;;;
+1D3B;MODIFIER LETTER CAPITAL REVERSED N;Lm;0;L;;;;;N;;;;;
+1D3C;MODIFIER LETTER CAPITAL O;Lm;0;L;<super> 004F;;;;N;;;;;
+1D3D;MODIFIER LETTER CAPITAL OU;Lm;0;L;<super> 0222;;;;N;;;;;
+1D3E;MODIFIER LETTER CAPITAL P;Lm;0;L;<super> 0050;;;;N;;;;;
+1D3F;MODIFIER LETTER CAPITAL R;Lm;0;L;<super> 0052;;;;N;;;;;
+1D40;MODIFIER LETTER CAPITAL T;Lm;0;L;<super> 0054;;;;N;;;;;
+1D41;MODIFIER LETTER CAPITAL U;Lm;0;L;<super> 0055;;;;N;;;;;
+1D42;MODIFIER LETTER CAPITAL W;Lm;0;L;<super> 0057;;;;N;;;;;
+1D43;MODIFIER LETTER SMALL A;Lm;0;L;<super> 0061;;;;N;;;;;
+1D44;MODIFIER LETTER SMALL TURNED A;Lm;0;L;<super> 0250;;;;N;;;;;
+1D45;MODIFIER LETTER SMALL ALPHA;Lm;0;L;<super> 0251;;;;N;;;;;
+1D46;MODIFIER LETTER SMALL TURNED AE;Lm;0;L;<super> 1D02;;;;N;;;;;
+1D47;MODIFIER LETTER SMALL B;Lm;0;L;<super> 0062;;;;N;;;;;
+1D48;MODIFIER LETTER SMALL D;Lm;0;L;<super> 0064;;;;N;;;;;
+1D49;MODIFIER LETTER SMALL E;Lm;0;L;<super> 0065;;;;N;;;;;
+1D4A;MODIFIER LETTER SMALL SCHWA;Lm;0;L;<super> 0259;;;;N;;;;;
+1D4B;MODIFIER LETTER SMALL OPEN E;Lm;0;L;<super> 025B;;;;N;;;;;
+1D4C;MODIFIER LETTER SMALL TURNED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;;
+1D4D;MODIFIER LETTER SMALL G;Lm;0;L;<super> 0067;;;;N;;;;;
+1D4E;MODIFIER LETTER SMALL TURNED I;Lm;0;L;;;;;N;;;;;
+1D4F;MODIFIER LETTER SMALL K;Lm;0;L;<super> 006B;;;;N;;;;;
+1D50;MODIFIER LETTER SMALL M;Lm;0;L;<super> 006D;;;;N;;;;;
+1D51;MODIFIER LETTER SMALL ENG;Lm;0;L;<super> 014B;;;;N;;;;;
+1D52;MODIFIER LETTER SMALL O;Lm;0;L;<super> 006F;;;;N;;;;;
+1D53;MODIFIER LETTER SMALL OPEN O;Lm;0;L;<super> 0254;;;;N;;;;;
+1D54;MODIFIER LETTER SMALL TOP HALF O;Lm;0;L;<super> 1D16;;;;N;;;;;
+1D55;MODIFIER LETTER SMALL BOTTOM HALF O;Lm;0;L;<super> 1D17;;;;N;;;;;
+1D56;MODIFIER LETTER SMALL P;Lm;0;L;<super> 0070;;;;N;;;;;
+1D57;MODIFIER LETTER SMALL T;Lm;0;L;<super> 0074;;;;N;;;;;
+1D58;MODIFIER LETTER SMALL U;Lm;0;L;<super> 0075;;;;N;;;;;
+1D59;MODIFIER LETTER SMALL SIDEWAYS U;Lm;0;L;<super> 1D1D;;;;N;;;;;
+1D5A;MODIFIER LETTER SMALL TURNED M;Lm;0;L;<super> 026F;;;;N;;;;;
+1D5B;MODIFIER LETTER SMALL V;Lm;0;L;<super> 0076;;;;N;;;;;
+1D5C;MODIFIER LETTER SMALL AIN;Lm;0;L;<super> 1D25;;;;N;;;;;
+1D5D;MODIFIER LETTER SMALL BETA;Lm;0;L;<super> 03B2;;;;N;;;;;
+1D5E;MODIFIER LETTER SMALL GREEK GAMMA;Lm;0;L;<super> 03B3;;;;N;;;;;
+1D5F;MODIFIER LETTER SMALL DELTA;Lm;0;L;<super> 03B4;;;;N;;;;;
+1D60;MODIFIER LETTER SMALL GREEK PHI;Lm;0;L;<super> 03C6;;;;N;;;;;
+1D61;MODIFIER LETTER SMALL CHI;Lm;0;L;<super> 03C7;;;;N;;;;;
+1D62;LATIN SUBSCRIPT SMALL LETTER I;Ll;0;L;<sub> 0069;;;;N;;;;;
+1D63;LATIN SUBSCRIPT SMALL LETTER R;Ll;0;L;<sub> 0072;;;;N;;;;;
+1D64;LATIN SUBSCRIPT SMALL LETTER U;Ll;0;L;<sub> 0075;;;;N;;;;;
+1D65;LATIN SUBSCRIPT SMALL LETTER V;Ll;0;L;<sub> 0076;;;;N;;;;;
+1D66;GREEK SUBSCRIPT SMALL LETTER BETA;Ll;0;L;<sub> 03B2;;;;N;;;;;
+1D67;GREEK SUBSCRIPT SMALL LETTER GAMMA;Ll;0;L;<sub> 03B3;;;;N;;;;;
+1D68;GREEK SUBSCRIPT SMALL LETTER RHO;Ll;0;L;<sub> 03C1;;;;N;;;;;
+1D69;GREEK SUBSCRIPT SMALL LETTER PHI;Ll;0;L;<sub> 03C6;;;;N;;;;;
+1D6A;GREEK SUBSCRIPT SMALL LETTER CHI;Ll;0;L;<sub> 03C7;;;;N;;;;;
+1D6B;LATIN SMALL LETTER UE;Ll;0;L;;;;;N;;;;;
+1D6C;LATIN SMALL LETTER B WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D6D;LATIN SMALL LETTER D WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D6E;LATIN SMALL LETTER F WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D6F;LATIN SMALL LETTER M WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D70;LATIN SMALL LETTER N WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D71;LATIN SMALL LETTER P WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D72;LATIN SMALL LETTER R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D73;LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D74;LATIN SMALL LETTER S WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D75;LATIN SMALL LETTER T WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D76;LATIN SMALL LETTER Z WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;;
+1D77;LATIN SMALL LETTER TURNED G;Ll;0;L;;;;;N;;;;;
+1D78;MODIFIER LETTER CYRILLIC EN;Lm;0;L;<super> 043D;;;;N;;;;;
+1D79;LATIN SMALL LETTER INSULAR G;Ll;0;L;;;;;N;;;A77D;;A77D
+1D7A;LATIN SMALL LETTER TH WITH STRIKETHROUGH;Ll;0;L;;;;;N;;;;;
+1D7B;LATIN SMALL CAPITAL LETTER I WITH STROKE;Ll;0;L;;;;;N;;;;;
+1D7C;LATIN SMALL LETTER IOTA WITH STROKE;Ll;0;L;;;;;N;;;;;
+1D7D;LATIN SMALL LETTER P WITH STROKE;Ll;0;L;;;;;N;;;2C63;;2C63
+1D7E;LATIN SMALL CAPITAL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;;;
+1D7F;LATIN SMALL LETTER UPSILON WITH STROKE;Ll;0;L;;;;;N;;;;;
+1D80;LATIN SMALL LETTER B WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D81;LATIN SMALL LETTER D WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D82;LATIN SMALL LETTER F WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D83;LATIN SMALL LETTER G WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D84;LATIN SMALL LETTER K WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D85;LATIN SMALL LETTER L WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D86;LATIN SMALL LETTER M WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D87;LATIN SMALL LETTER N WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D88;LATIN SMALL LETTER P WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D89;LATIN SMALL LETTER R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D8A;LATIN SMALL LETTER S WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D8B;LATIN SMALL LETTER ESH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D8C;LATIN SMALL LETTER V WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D8D;LATIN SMALL LETTER X WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D8E;LATIN SMALL LETTER Z WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1D8F;LATIN SMALL LETTER A WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D90;LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D91;LATIN SMALL LETTER D WITH HOOK AND TAIL;Ll;0;L;;;;;N;;;;;
+1D92;LATIN SMALL LETTER E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D93;LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D94;LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D95;LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D96;LATIN SMALL LETTER I WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D97;LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D98;LATIN SMALL LETTER ESH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D99;LATIN SMALL LETTER U WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D9A;LATIN SMALL LETTER EZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1D9B;MODIFIER LETTER SMALL TURNED ALPHA;Lm;0;L;<super> 0252;;;;N;;;;;
+1D9C;MODIFIER LETTER SMALL C;Lm;0;L;<super> 0063;;;;N;;;;;
+1D9D;MODIFIER LETTER SMALL C WITH CURL;Lm;0;L;<super> 0255;;;;N;;;;;
+1D9E;MODIFIER LETTER SMALL ETH;Lm;0;L;<super> 00F0;;;;N;;;;;
+1D9F;MODIFIER LETTER SMALL REVERSED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;;
+1DA0;MODIFIER LETTER SMALL F;Lm;0;L;<super> 0066;;;;N;;;;;
+1DA1;MODIFIER LETTER SMALL DOTLESS J WITH STROKE;Lm;0;L;<super> 025F;;;;N;;;;;
+1DA2;MODIFIER LETTER SMALL SCRIPT G;Lm;0;L;<super> 0261;;;;N;;;;;
+1DA3;MODIFIER LETTER SMALL TURNED H;Lm;0;L;<super> 0265;;;;N;;;;;
+1DA4;MODIFIER LETTER SMALL I WITH STROKE;Lm;0;L;<super> 0268;;;;N;;;;;
+1DA5;MODIFIER LETTER SMALL IOTA;Lm;0;L;<super> 0269;;;;N;;;;;
+1DA6;MODIFIER LETTER SMALL CAPITAL I;Lm;0;L;<super> 026A;;;;N;;;;;
+1DA7;MODIFIER LETTER SMALL CAPITAL I WITH STROKE;Lm;0;L;<super> 1D7B;;;;N;;;;;
+1DA8;MODIFIER LETTER SMALL J WITH CROSSED-TAIL;Lm;0;L;<super> 029D;;;;N;;;;;
+1DA9;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK;Lm;0;L;<super> 026D;;;;N;;;;;
+1DAA;MODIFIER LETTER SMALL L WITH PALATAL HOOK;Lm;0;L;<super> 1D85;;;;N;;;;;
+1DAB;MODIFIER LETTER SMALL CAPITAL L;Lm;0;L;<super> 029F;;;;N;;;;;
+1DAC;MODIFIER LETTER SMALL M WITH HOOK;Lm;0;L;<super> 0271;;;;N;;;;;
+1DAD;MODIFIER LETTER SMALL TURNED M WITH LONG LEG;Lm;0;L;<super> 0270;;;;N;;;;;
+1DAE;MODIFIER LETTER SMALL N WITH LEFT HOOK;Lm;0;L;<super> 0272;;;;N;;;;;
+1DAF;MODIFIER LETTER SMALL N WITH RETROFLEX HOOK;Lm;0;L;<super> 0273;;;;N;;;;;
+1DB0;MODIFIER LETTER SMALL CAPITAL N;Lm;0;L;<super> 0274;;;;N;;;;;
+1DB1;MODIFIER LETTER SMALL BARRED O;Lm;0;L;<super> 0275;;;;N;;;;;
+1DB2;MODIFIER LETTER SMALL PHI;Lm;0;L;<super> 0278;;;;N;;;;;
+1DB3;MODIFIER LETTER SMALL S WITH HOOK;Lm;0;L;<super> 0282;;;;N;;;;;
+1DB4;MODIFIER LETTER SMALL ESH;Lm;0;L;<super> 0283;;;;N;;;;;
+1DB5;MODIFIER LETTER SMALL T WITH PALATAL HOOK;Lm;0;L;<super> 01AB;;;;N;;;;;
+1DB6;MODIFIER LETTER SMALL U BAR;Lm;0;L;<super> 0289;;;;N;;;;;
+1DB7;MODIFIER LETTER SMALL UPSILON;Lm;0;L;<super> 028A;;;;N;;;;;
+1DB8;MODIFIER LETTER SMALL CAPITAL U;Lm;0;L;<super> 1D1C;;;;N;;;;;
+1DB9;MODIFIER LETTER SMALL V WITH HOOK;Lm;0;L;<super> 028B;;;;N;;;;;
+1DBA;MODIFIER LETTER SMALL TURNED V;Lm;0;L;<super> 028C;;;;N;;;;;
+1DBB;MODIFIER LETTER SMALL Z;Lm;0;L;<super> 007A;;;;N;;;;;
+1DBC;MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK;Lm;0;L;<super> 0290;;;;N;;;;;
+1DBD;MODIFIER LETTER SMALL Z WITH CURL;Lm;0;L;<super> 0291;;;;N;;;;;
+1DBE;MODIFIER LETTER SMALL EZH;Lm;0;L;<super> 0292;;;;N;;;;;
+1DBF;MODIFIER LETTER SMALL THETA;Lm;0;L;<super> 03B8;;;;N;;;;;
+1DC0;COMBINING DOTTED GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;;
+1DC1;COMBINING DOTTED ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;;
+1DC2;COMBINING SNAKE BELOW;Mn;220;NSM;;;;;N;;;;;
+1DC3;COMBINING SUSPENSION MARK;Mn;230;NSM;;;;;N;;;;;
+1DC4;COMBINING MACRON-ACUTE;Mn;230;NSM;;;;;N;;;;;
+1DC5;COMBINING GRAVE-MACRON;Mn;230;NSM;;;;;N;;;;;
+1DC6;COMBINING MACRON-GRAVE;Mn;230;NSM;;;;;N;;;;;
+1DC7;COMBINING ACUTE-MACRON;Mn;230;NSM;;;;;N;;;;;
+1DC8;COMBINING GRAVE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;;
+1DC9;COMBINING ACUTE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;;
+1DCA;COMBINING LATIN SMALL LETTER R BELOW;Mn;220;NSM;;;;;N;;;;;
+1DCB;COMBINING BREVE-MACRON;Mn;230;NSM;;;;;N;;;;;
+1DCC;COMBINING MACRON-BREVE;Mn;230;NSM;;;;;N;;;;;
+1DCD;COMBINING DOUBLE CIRCUMFLEX ABOVE;Mn;234;NSM;;;;;N;;;;;
+1DCE;COMBINING OGONEK ABOVE;Mn;214;NSM;;;;;N;;;;;
+1DCF;COMBINING ZIGZAG BELOW;Mn;220;NSM;;;;;N;;;;;
+1DD0;COMBINING IS BELOW;Mn;202;NSM;;;;;N;;;;;
+1DD1;COMBINING UR ABOVE;Mn;230;NSM;;;;;N;;;;;
+1DD2;COMBINING US ABOVE;Mn;230;NSM;;;;;N;;;;;
+1DD3;COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE;Mn;230;NSM;;;;;N;;;;;
+1DD4;COMBINING LATIN SMALL LETTER AE;Mn;230;NSM;;;;;N;;;;;
+1DD5;COMBINING LATIN SMALL LETTER AO;Mn;230;NSM;;;;;N;;;;;
+1DD6;COMBINING LATIN SMALL LETTER AV;Mn;230;NSM;;;;;N;;;;;
+1DD7;COMBINING LATIN SMALL LETTER C CEDILLA;Mn;230;NSM;;;;;N;;;;;
+1DD8;COMBINING LATIN SMALL LETTER INSULAR D;Mn;230;NSM;;;;;N;;;;;
+1DD9;COMBINING LATIN SMALL LETTER ETH;Mn;230;NSM;;;;;N;;;;;
+1DDA;COMBINING LATIN SMALL LETTER G;Mn;230;NSM;;;;;N;;;;;
+1DDB;COMBINING LATIN LETTER SMALL CAPITAL G;Mn;230;NSM;;;;;N;;;;;
+1DDC;COMBINING LATIN SMALL LETTER K;Mn;230;NSM;;;;;N;;;;;
+1DDD;COMBINING LATIN SMALL LETTER L;Mn;230;NSM;;;;;N;;;;;
+1DDE;COMBINING LATIN LETTER SMALL CAPITAL L;Mn;230;NSM;;;;;N;;;;;
+1DDF;COMBINING LATIN LETTER SMALL CAPITAL M;Mn;230;NSM;;;;;N;;;;;
+1DE0;COMBINING LATIN SMALL LETTER N;Mn;230;NSM;;;;;N;;;;;
+1DE1;COMBINING LATIN LETTER SMALL CAPITAL N;Mn;230;NSM;;;;;N;;;;;
+1DE2;COMBINING LATIN LETTER SMALL CAPITAL R;Mn;230;NSM;;;;;N;;;;;
+1DE3;COMBINING LATIN SMALL LETTER R ROTUNDA;Mn;230;NSM;;;;;N;;;;;
+1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;;
+1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;;
+1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;;
+1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;;
+1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;;
+1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;;
+1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01;
+1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00
+1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03;
+1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02
+1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05;
+1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04
+1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07;
+1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06
+1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09;
+1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08
+1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B;
+1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A
+1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D;
+1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C
+1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F;
+1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E
+1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11;
+1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10
+1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13;
+1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12
+1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15;
+1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14
+1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17;
+1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16
+1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19;
+1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18
+1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B;
+1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A
+1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D;
+1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C
+1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F;
+1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E
+1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21;
+1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20
+1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23;
+1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22
+1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25;
+1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24
+1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27;
+1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26
+1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29;
+1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28
+1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B;
+1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A
+1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D;
+1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C
+1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F;
+1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E
+1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31;
+1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30
+1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33;
+1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32
+1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35;
+1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34
+1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37;
+1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36
+1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39;
+1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38
+1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B;
+1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A
+1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D;
+1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C
+1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F;
+1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E
+1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41;
+1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40
+1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43;
+1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42
+1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45;
+1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44
+1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47;
+1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46
+1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49;
+1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48
+1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B;
+1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A
+1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D;
+1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C
+1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F;
+1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E
+1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51;
+1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50
+1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53;
+1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52
+1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55;
+1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54
+1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57;
+1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56
+1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59;
+1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58
+1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B;
+1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A
+1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D;
+1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C
+1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F;
+1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E
+1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61;
+1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60
+1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63;
+1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62
+1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65;
+1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64
+1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67;
+1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66
+1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69;
+1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68
+1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B;
+1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A
+1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D;
+1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C
+1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F;
+1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E
+1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71;
+1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70
+1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73;
+1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72
+1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75;
+1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74
+1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77;
+1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76
+1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79;
+1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78
+1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B;
+1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A
+1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D;
+1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C
+1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F;
+1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E
+1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81;
+1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80
+1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83;
+1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82
+1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85;
+1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84
+1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87;
+1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86
+1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89;
+1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88
+1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B;
+1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A
+1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D;
+1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C
+1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F;
+1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E
+1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91;
+1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90
+1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93;
+1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92
+1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95;
+1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94
+1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;;
+1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;;
+1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;;
+1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;;
+1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L;<compat> 0061 02BE;;;;N;;;;;
+1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60
+1E9C;LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;;;
+1E9D;LATIN SMALL LETTER LONG S WITH HIGH STROKE;Ll;0;L;;;;;N;;;;;
+1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF;
+1E9F;LATIN SMALL LETTER DELTA;Ll;0;L;;;;;N;;;;;
+1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1;
+1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0
+1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3;
+1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2
+1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5;
+1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4
+1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7;
+1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6
+1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9;
+1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8
+1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB;
+1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA
+1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD;
+1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC
+1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF;
+1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE
+1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1;
+1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0
+1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3;
+1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2
+1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5;
+1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4
+1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7;
+1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6
+1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9;
+1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8
+1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB;
+1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA
+1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD;
+1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC
+1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF;
+1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE
+1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1;
+1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0
+1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3;
+1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2
+1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5;
+1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4
+1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7;
+1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6
+1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9;
+1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8
+1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB;
+1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA
+1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD;
+1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC
+1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF;
+1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE
+1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1;
+1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0
+1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3;
+1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2
+1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5;
+1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4
+1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7;
+1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6
+1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9;
+1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8
+1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB;
+1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA
+1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD;
+1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC
+1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF;
+1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE
+1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1;
+1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0
+1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3;
+1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2
+1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5;
+1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4
+1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7;
+1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6
+1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9;
+1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8
+1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB;
+1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA
+1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED;
+1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC
+1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF;
+1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE
+1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1;
+1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0
+1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3;
+1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2
+1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5;
+1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4
+1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7;
+1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6
+1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9;
+1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8
+1EFA;LATIN CAPITAL LETTER MIDDLE-WELSH LL;Lu;0;L;;;;;N;;;;1EFB;
+1EFB;LATIN SMALL LETTER MIDDLE-WELSH LL;Ll;0;L;;;;;N;;;1EFA;;1EFA
+1EFC;LATIN CAPITAL LETTER MIDDLE-WELSH V;Lu;0;L;;;;;N;;;;1EFD;
+1EFD;LATIN SMALL LETTER MIDDLE-WELSH V;Ll;0;L;;;;;N;;;1EFC;;1EFC
+1EFE;LATIN CAPITAL LETTER Y WITH LOOP;Lu;0;L;;;;;N;;;;1EFF;
+1EFF;LATIN SMALL LETTER Y WITH LOOP;Ll;0;L;;;;;N;;;1EFE;;1EFE
+1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08
+1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09
+1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A
+1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B
+1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C
+1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D
+1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E
+1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F
+1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00;
+1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01;
+1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02;
+1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03;
+1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04;
+1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05;
+1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06;
+1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07;
+1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18
+1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19
+1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A
+1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B
+1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C
+1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D
+1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10;
+1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11;
+1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12;
+1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13;
+1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14;
+1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15;
+1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28
+1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29
+1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A
+1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B
+1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C
+1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D
+1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E
+1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F
+1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20;
+1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21;
+1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22;
+1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23;
+1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24;
+1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25;
+1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26;
+1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27;
+1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38
+1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39
+1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A
+1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B
+1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C
+1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D
+1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E
+1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F
+1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30;
+1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31;
+1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32;
+1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33;
+1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34;
+1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35;
+1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36;
+1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37;
+1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48
+1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49
+1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A
+1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B
+1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C
+1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D
+1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40;
+1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41;
+1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42;
+1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43;
+1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44;
+1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45;
+1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;;
+1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59
+1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;;
+1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B
+1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;;
+1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D
+1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;;
+1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F
+1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51;
+1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53;
+1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55;
+1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57;
+1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68
+1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69
+1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A
+1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B
+1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C
+1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D
+1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E
+1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F
+1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60;
+1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61;
+1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62;
+1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63;
+1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64;
+1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65;
+1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66;
+1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67;
+1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA
+1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB
+1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8
+1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9
+1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA
+1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB
+1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA
+1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB
+1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8
+1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9
+1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA
+1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB
+1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA
+1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB
+1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88
+1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89
+1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A
+1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B
+1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C
+1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D
+1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E
+1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F
+1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80;
+1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81;
+1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82;
+1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83;
+1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84;
+1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85;
+1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86;
+1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87;
+1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98
+1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99
+1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A
+1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B
+1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C
+1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D
+1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E
+1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F
+1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90;
+1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91;
+1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92;
+1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93;
+1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94;
+1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95;
+1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96;
+1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97;
+1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8
+1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9
+1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA
+1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB
+1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC
+1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD
+1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE
+1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF
+1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0;
+1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1;
+1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2;
+1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3;
+1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4;
+1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5;
+1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6;
+1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7;
+1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8
+1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9
+1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;;
+1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC
+1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;;
+1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;;
+1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;;
+1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0;
+1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1;
+1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70;
+1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71;
+1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3;
+1FBD;GREEK KORONIS;Sk;0;ON;<compat> 0020 0313;;;;N;;;;;
+1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399
+1FBF;GREEK PSILI;Sk;0;ON;<compat> 0020 0313;;;;N;;;;;
+1FC0;GREEK PERISPOMENI;Sk;0;ON;<compat> 0020 0342;;;;N;;;;;
+1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;;
+1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;;
+1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC
+1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;;
+1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;;
+1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;;
+1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72;
+1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73;
+1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74;
+1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75;
+1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3;
+1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;;
+1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;;
+1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;;
+1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8
+1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9
+1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;;
+1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;;
+1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;;
+1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;;
+1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0;
+1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1;
+1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76;
+1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77;
+1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;;
+1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;;
+1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;;
+1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8
+1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9
+1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;;
+1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;;
+1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;;
+1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC
+1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;;
+1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;;
+1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0;
+1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1;
+1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A;
+1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B;
+1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5;
+1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;;
+1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;;
+1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;;
+1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;;
+1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC
+1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;;
+1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;;
+1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;;
+1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78;
+1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79;
+1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C;
+1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D;
+1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3;
+1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;;
+1FFE;GREEK DASIA;Sk;0;ON;<compat> 0020 0314;;;;N;;;;;
+2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
+2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
+2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
+2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+200B;ZERO WIDTH SPACE;Cf;0;BN;;;;;N;;;;;
+200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;;
+200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;;
+200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;;
+200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;;
+2010;HYPHEN;Pd;0;ON;;;;;N;;;;;
+2011;NON-BREAKING HYPHEN;Pd;0;ON;<noBreak> 2010;;;;N;;;;;
+2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;;
+2013;EN DASH;Pd;0;ON;;;;;N;;;;;
+2014;EM DASH;Pd;0;ON;;;;;N;;;;;
+2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;;
+2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;;
+2017;DOUBLE LOW LINE;Po;0;ON;<compat> 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;;
+2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;;
+2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;;
+201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;;
+201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;;
+201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;;
+201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;;
+201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;;
+201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;;
+2020;DAGGER;Po;0;ON;;;;;N;;;;;
+2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;;
+2022;BULLET;Po;0;ON;;;;;N;;;;;
+2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;;
+2024;ONE DOT LEADER;Po;0;ON;<compat> 002E;;;;N;;;;;
+2025;TWO DOT LEADER;Po;0;ON;<compat> 002E 002E;;;;N;;;;;
+2026;HORIZONTAL ELLIPSIS;Po;0;ON;<compat> 002E 002E 002E;;;;N;;;;;
+2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;;
+2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;;
+2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;;
+202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;;
+202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;;
+202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;;
+202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;;
+202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;;
+202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
+2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;;
+2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;;
+2032;PRIME;Po;0;ET;;;;;N;;;;;
+2033;DOUBLE PRIME;Po;0;ET;<compat> 2032 2032;;;;N;;;;;
+2034;TRIPLE PRIME;Po;0;ET;<compat> 2032 2032 2032;;;;N;;;;;
+2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;;
+2036;REVERSED DOUBLE PRIME;Po;0;ON;<compat> 2035 2035;;;;N;;;;;
+2037;REVERSED TRIPLE PRIME;Po;0;ON;<compat> 2035 2035 2035;;;;N;;;;;
+2038;CARET;Po;0;ON;;;;;N;;;;;
+2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;;
+203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;;
+203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;;
+203C;DOUBLE EXCLAMATION MARK;Po;0;ON;<compat> 0021 0021;;;;N;;;;;
+203D;INTERROBANG;Po;0;ON;;;;;N;;;;;
+203E;OVERLINE;Po;0;ON;<compat> 0020 0305;;;;N;SPACING OVERSCORE;;;;
+203F;UNDERTIE;Pc;0;ON;;;;;N;;;;;
+2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;;
+2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;;
+2042;ASTERISM;Po;0;ON;;;;;N;;;;;
+2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;;
+2044;FRACTION SLASH;Sm;0;CS;;;;;N;;;;;
+2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;;
+2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;;
+2047;DOUBLE QUESTION MARK;Po;0;ON;<compat> 003F 003F;;;;N;;;;;
+2048;QUESTION EXCLAMATION MARK;Po;0;ON;<compat> 003F 0021;;;;N;;;;;
+2049;EXCLAMATION QUESTION MARK;Po;0;ON;<compat> 0021 003F;;;;N;;;;;
+204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;;
+204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;;
+204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;;
+204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;;
+204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;;
+204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;;
+2050;CLOSE UP;Po;0;ON;;;;;N;;;;;
+2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;;
+2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;;
+2053;SWUNG DASH;Po;0;ON;;;;;N;;;;;
+2054;INVERTED UNDERTIE;Pc;0;ON;;;;;N;;;;;
+2055;FLOWER PUNCTUATION MARK;Po;0;ON;;;;;N;;;;;
+2056;THREE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+2057;QUADRUPLE PRIME;Po;0;ON;<compat> 2032 2032 2032 2032;;;;N;;;;;
+2058;FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+2059;FIVE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+205A;TWO DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+205B;FOUR DOT MARK;Po;0;ON;;;;;N;;;;;
+205C;DOTTED CROSS;Po;0;ON;;;;;N;;;;;
+205D;TRICOLON;Po;0;ON;;;;;N;;;;;
+205E;VERTICAL FOUR DOTS;Po;0;ON;;;;;N;;;;;
+205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
+2060;WORD JOINER;Cf;0;BN;;;;;N;;;;;
+2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;;
+2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;;
+2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;;
+2064;INVISIBLE PLUS;Cf;0;BN;;;;;N;;;;;
+206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;;
+206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;;
+206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;;
+206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;;
+206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;;
+206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;;
+2070;SUPERSCRIPT ZERO;No;0;EN;<super> 0030;;0;0;N;SUPERSCRIPT DIGIT ZERO;;;;
+2071;SUPERSCRIPT LATIN SMALL LETTER I;Lm;0;L;<super> 0069;;;;N;;;;;
+2074;SUPERSCRIPT FOUR;No;0;EN;<super> 0034;;4;4;N;SUPERSCRIPT DIGIT FOUR;;;;
+2075;SUPERSCRIPT FIVE;No;0;EN;<super> 0035;;5;5;N;SUPERSCRIPT DIGIT FIVE;;;;
+2076;SUPERSCRIPT SIX;No;0;EN;<super> 0036;;6;6;N;SUPERSCRIPT DIGIT SIX;;;;
+2077;SUPERSCRIPT SEVEN;No;0;EN;<super> 0037;;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;;
+2078;SUPERSCRIPT EIGHT;No;0;EN;<super> 0038;;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;;
+2079;SUPERSCRIPT NINE;No;0;EN;<super> 0039;;9;9;N;SUPERSCRIPT DIGIT NINE;;;;
+207A;SUPERSCRIPT PLUS SIGN;Sm;0;ES;<super> 002B;;;;N;;;;;
+207B;SUPERSCRIPT MINUS;Sm;0;ES;<super> 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;;
+207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON;<super> 003D;;;;N;;;;;
+207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON;<super> 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;;
+207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<super> 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;;
+207F;SUPERSCRIPT LATIN SMALL LETTER N;Lm;0;L;<super> 006E;;;;N;;;;;
+2080;SUBSCRIPT ZERO;No;0;EN;<sub> 0030;;0;0;N;SUBSCRIPT DIGIT ZERO;;;;
+2081;SUBSCRIPT ONE;No;0;EN;<sub> 0031;;1;1;N;SUBSCRIPT DIGIT ONE;;;;
+2082;SUBSCRIPT TWO;No;0;EN;<sub> 0032;;2;2;N;SUBSCRIPT DIGIT TWO;;;;
+2083;SUBSCRIPT THREE;No;0;EN;<sub> 0033;;3;3;N;SUBSCRIPT DIGIT THREE;;;;
+2084;SUBSCRIPT FOUR;No;0;EN;<sub> 0034;;4;4;N;SUBSCRIPT DIGIT FOUR;;;;
+2085;SUBSCRIPT FIVE;No;0;EN;<sub> 0035;;5;5;N;SUBSCRIPT DIGIT FIVE;;;;
+2086;SUBSCRIPT SIX;No;0;EN;<sub> 0036;;6;6;N;SUBSCRIPT DIGIT SIX;;;;
+2087;SUBSCRIPT SEVEN;No;0;EN;<sub> 0037;;7;7;N;SUBSCRIPT DIGIT SEVEN;;;;
+2088;SUBSCRIPT EIGHT;No;0;EN;<sub> 0038;;8;8;N;SUBSCRIPT DIGIT EIGHT;;;;
+2089;SUBSCRIPT NINE;No;0;EN;<sub> 0039;;9;9;N;SUBSCRIPT DIGIT NINE;;;;
+208A;SUBSCRIPT PLUS SIGN;Sm;0;ES;<sub> 002B;;;;N;;;;;
+208B;SUBSCRIPT MINUS;Sm;0;ES;<sub> 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;;
+208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON;<sub> 003D;;;;N;;;;;
+208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON;<sub> 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;;
+208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<sub> 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;;
+2090;LATIN SUBSCRIPT SMALL LETTER A;Lm;0;L;<sub> 0061;;;;N;;;;;
+2091;LATIN SUBSCRIPT SMALL LETTER E;Lm;0;L;<sub> 0065;;;;N;;;;;
+2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L;<sub> 006F;;;;N;;;;;
+2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L;<sub> 0078;;;;N;;;;;
+2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L;<sub> 0259;;;;N;;;;;
+20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;;
+20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;;
+20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;;
+20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;;
+20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;;
+20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;;
+20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;;
+20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;;
+20A8;RUPEE SIGN;Sc;0;ET;<compat> 0052 0073;;;;N;;;;;
+20A9;WON SIGN;Sc;0;ET;;;;;N;;;;;
+20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;;
+20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;;
+20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;;
+20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;;
+20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;;
+20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;;
+20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;;
+20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;;
+20B2;GUARANI SIGN;Sc;0;ET;;;;;N;;;;;
+20B3;AUSTRAL SIGN;Sc;0;ET;;;;;N;;;;;
+20B4;HRYVNIA SIGN;Sc;0;ET;;;;;N;;;;;
+20B5;CEDI SIGN;Sc;0;ET;;;;;N;;;;;
+20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;;
+20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;;
+20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;;
+20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;;
+20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;;
+20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;;
+20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;;
+20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;;
+20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;;
+20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;;
+20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;;
+20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;;
+20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;;
+20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;;
+20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;;
+20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;;
+20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;;
+20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;;
+20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;;
+20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;;
+20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;;
+20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;;
+20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;;
+20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;;
+20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;;
+20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;;
+20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;;
+20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;;
+20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;;
+20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;;
+20EB;COMBINING LONG DOUBLE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;;
+20EC;COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;;
+20ED;COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;;
+20EE;COMBINING LEFT ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
+20EF;COMBINING RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;;
+20F0;COMBINING ASTERISK ABOVE;Mn;230;NSM;;;;;N;;;;;
+2100;ACCOUNT OF;So;0;ON;<compat> 0061 002F 0063;;;;N;;;;;
+2101;ADDRESSED TO THE SUBJECT;So;0;ON;<compat> 0061 002F 0073;;;;N;;;;;
+2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L;<font> 0043;;;;N;DOUBLE-STRUCK C;;;;
+2103;DEGREE CELSIUS;So;0;ON;<compat> 00B0 0043;;;;N;DEGREES CENTIGRADE;;;;
+2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;;
+2105;CARE OF;So;0;ON;<compat> 0063 002F 006F;;;;N;;;;;
+2106;CADA UNA;So;0;ON;<compat> 0063 002F 0075;;;;N;;;;;
+2107;EULER CONSTANT;Lu;0;L;<compat> 0190;;;;N;EULERS;;;;
+2108;SCRUPLE;So;0;ON;;;;;N;;;;;
+2109;DEGREE FAHRENHEIT;So;0;ON;<compat> 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;;
+210A;SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+210B;SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;SCRIPT H;;;;
+210C;BLACK-LETTER CAPITAL H;Lu;0;L;<font> 0048;;;;N;BLACK-LETTER H;;;;
+210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L;<font> 0048;;;;N;DOUBLE-STRUCK H;;;;
+210E;PLANCK CONSTANT;Ll;0;L;<font> 0068;;;;N;;;;;
+210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L;<font> 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;;
+2110;SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;SCRIPT I;;;;
+2111;BLACK-LETTER CAPITAL I;Lu;0;L;<font> 0049;;;;N;BLACK-LETTER I;;;;
+2112;SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;SCRIPT L;;;;
+2113;SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;;
+2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L;<font> 004E;;;;N;DOUBLE-STRUCK N;;;;
+2116;NUMERO SIGN;So;0;ON;<compat> 004E 006F;;;;N;NUMERO;;;;
+2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;;
+2118;SCRIPT CAPITAL P;So;0;ON;;;;;N;SCRIPT P;;;;
+2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L;<font> 0050;;;;N;DOUBLE-STRUCK P;;;;
+211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L;<font> 0051;;;;N;DOUBLE-STRUCK Q;;;;
+211B;SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;SCRIPT R;;;;
+211C;BLACK-LETTER CAPITAL R;Lu;0;L;<font> 0052;;;;N;BLACK-LETTER R;;;;
+211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L;<font> 0052;;;;N;DOUBLE-STRUCK R;;;;
+211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;;
+211F;RESPONSE;So;0;ON;;;;;N;;;;;
+2120;SERVICE MARK;So;0;ON;<super> 0053 004D;;;;N;;;;;
+2121;TELEPHONE SIGN;So;0;ON;<compat> 0054 0045 004C;;;;N;T E L SYMBOL;;;;
+2122;TRADE MARK SIGN;So;0;ON;<super> 0054 004D;;;;N;TRADEMARK;;;;
+2123;VERSICLE;So;0;ON;;;;;N;;;;;
+2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L;<font> 005A;;;;N;DOUBLE-STRUCK Z;;;;
+2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;;
+2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9;
+2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;;
+2128;BLACK-LETTER CAPITAL Z;Lu;0;L;<font> 005A;;;;N;BLACK-LETTER Z;;;;
+2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;;
+212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B;
+212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5;
+212C;SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;SCRIPT B;;;;
+212D;BLACK-LETTER CAPITAL C;Lu;0;L;<font> 0043;;;;N;BLACK-LETTER C;;;;
+212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;;
+212F;SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+2130;SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;SCRIPT E;;;;
+2131;SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;SCRIPT F;;;;
+2132;TURNED CAPITAL F;Lu;0;L;;;;;N;TURNED F;;;214E;
+2133;SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;SCRIPT M;;;;
+2134;SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+2135;ALEF SYMBOL;Lo;0;L;<compat> 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;;
+2136;BET SYMBOL;Lo;0;L;<compat> 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;;
+2137;GIMEL SYMBOL;Lo;0;L;<compat> 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;;
+2138;DALET SYMBOL;Lo;0;L;<compat> 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;;
+2139;INFORMATION SOURCE;Ll;0;L;<font> 0069;;;;N;;;;;
+213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;;
+213B;FACSIMILE SIGN;So;0;ON;<compat> 0046 0041 0058;;;;N;;;;;
+213C;DOUBLE-STRUCK SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
+213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
+213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
+213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
+2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON;<font> 2211;;;;Y;;;;;
+2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;;
+2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;;
+2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;;
+2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;;
+2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+214A;PROPERTY LINE;So;0;ON;;;;;N;;;;;
+214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;;
+214C;PER SIGN;So;0;ON;;;;;N;;;;;
+214D;AKTIESELSKAB;So;0;ON;;;;;N;;;;;
+214E;TURNED SMALL F;Ll;0;L;;;;;N;;;2132;;2132
+214F;SYMBOL FOR SAMARITAN SOURCE;So;0;L;;;;;N;;;;;
+2150;VULGAR FRACTION ONE SEVENTH;No;0;ON;<fraction> 0031 2044 0037;;;1/7;N;;;;;
+2151;VULGAR FRACTION ONE NINTH;No;0;ON;<fraction> 0031 2044 0039;;;1/9;N;;;;;
+2152;VULGAR FRACTION ONE TENTH;No;0;ON;<fraction> 0031 2044 0031 0030;;;1/10;N;;;;;
+2153;VULGAR FRACTION ONE THIRD;No;0;ON;<fraction> 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;;
+2154;VULGAR FRACTION TWO THIRDS;No;0;ON;<fraction> 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;;
+2155;VULGAR FRACTION ONE FIFTH;No;0;ON;<fraction> 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;;
+2156;VULGAR FRACTION TWO FIFTHS;No;0;ON;<fraction> 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;;
+2157;VULGAR FRACTION THREE FIFTHS;No;0;ON;<fraction> 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;;
+2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON;<fraction> 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;;
+2159;VULGAR FRACTION ONE SIXTH;No;0;ON;<fraction> 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;;
+215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON;<fraction> 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;;
+215B;VULGAR FRACTION ONE EIGHTH;No;0;ON;<fraction> 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;;
+215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON;<fraction> 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;;
+215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON;<fraction> 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;;
+215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON;<fraction> 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;;
+215F;FRACTION NUMERATOR ONE;No;0;ON;<fraction> 0031 2044;;;1;N;;;;;
+2160;ROMAN NUMERAL ONE;Nl;0;L;<compat> 0049;;;1;N;;;;2170;
+2161;ROMAN NUMERAL TWO;Nl;0;L;<compat> 0049 0049;;;2;N;;;;2171;
+2162;ROMAN NUMERAL THREE;Nl;0;L;<compat> 0049 0049 0049;;;3;N;;;;2172;
+2163;ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0049 0056;;;4;N;;;;2173;
+2164;ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0056;;;5;N;;;;2174;
+2165;ROMAN NUMERAL SIX;Nl;0;L;<compat> 0056 0049;;;6;N;;;;2175;
+2166;ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0056 0049 0049;;;7;N;;;;2176;
+2167;ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0056 0049 0049 0049;;;8;N;;;;2177;
+2168;ROMAN NUMERAL NINE;Nl;0;L;<compat> 0049 0058;;;9;N;;;;2178;
+2169;ROMAN NUMERAL TEN;Nl;0;L;<compat> 0058;;;10;N;;;;2179;
+216A;ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0058 0049;;;11;N;;;;217A;
+216B;ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0058 0049 0049;;;12;N;;;;217B;
+216C;ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 004C;;;50;N;;;;217C;
+216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0043;;;100;N;;;;217D;
+216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0044;;;500;N;;;;217E;
+216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 004D;;;1000;N;;;;217F;
+2170;SMALL ROMAN NUMERAL ONE;Nl;0;L;<compat> 0069;;;1;N;;;2160;;2160
+2171;SMALL ROMAN NUMERAL TWO;Nl;0;L;<compat> 0069 0069;;;2;N;;;2161;;2161
+2172;SMALL ROMAN NUMERAL THREE;Nl;0;L;<compat> 0069 0069 0069;;;3;N;;;2162;;2162
+2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0069 0076;;;4;N;;;2163;;2163
+2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0076;;;5;N;;;2164;;2164
+2175;SMALL ROMAN NUMERAL SIX;Nl;0;L;<compat> 0076 0069;;;6;N;;;2165;;2165
+2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0076 0069 0069;;;7;N;;;2166;;2166
+2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0076 0069 0069 0069;;;8;N;;;2167;;2167
+2178;SMALL ROMAN NUMERAL NINE;Nl;0;L;<compat> 0069 0078;;;9;N;;;2168;;2168
+2179;SMALL ROMAN NUMERAL TEN;Nl;0;L;<compat> 0078;;;10;N;;;2169;;2169
+217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0078 0069;;;11;N;;;216A;;216A
+217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0078 0069 0069;;;12;N;;;216B;;216B
+217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 006C;;;50;N;;;216C;;216C
+217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0063;;;100;N;;;216D;;216D
+217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0064;;;500;N;;;216E;;216E
+217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 006D;;;1000;N;;;216F;;216F
+2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;;
+2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;;
+2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;;
+2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Lu;0;L;;;;;N;;;;2184;
+2184;LATIN SMALL LETTER REVERSED C;Ll;0;L;;;;;N;;;2183;;2183
+2185;ROMAN NUMERAL SIX LATE FORM;Nl;0;L;;;;6;N;;;;;
+2186;ROMAN NUMERAL FIFTY EARLY FORM;Nl;0;L;;;;50;N;;;;;
+2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;;
+2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;;
+2189;VULGAR FRACTION ZERO THIRDS;No;0;ON;<fraction> 0030 2044 0033;;;0;N;;;;;
+2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;;
+2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;;
+2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;;
+2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;;
+2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;;
+2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;;
+2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;;
+2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;;
+2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;;
+2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;;
+219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;;
+219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;;
+219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;;
+219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;;
+219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;;
+219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;;
+21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;;
+21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;;
+21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;;
+21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;;
+21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;;
+21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;;
+21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;;
+21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;;
+21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;;
+21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;;
+21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;;
+21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;;
+21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;;
+21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;;
+21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;;
+21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;;
+21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;;
+21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;;
+21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;;
+21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;;
+21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;;
+21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;;
+21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;;
+21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;;
+21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;;
+21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;;
+21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;;
+21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;;
+21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;;
+21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;;
+21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;;
+21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;;
+21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;;
+21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;;
+21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;;
+21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;;
+21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;;
+21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;;
+21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;;
+21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;;
+21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;;
+21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;;
+21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;;
+21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;;
+21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;;
+21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;;
+21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;;
+21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;;
+21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;;
+21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;;
+21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;;
+21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;;
+21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
+21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;;
+21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;;
+21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;;
+21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;;
+21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;;
+21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;;
+21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;;
+21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;;
+21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;;
+21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;;
+21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;;
+21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;;
+21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;;
+21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;;
+21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;;
+21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;;
+21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;;
+21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;;
+21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;;
+21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;;
+21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;;
+21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;;
+21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;;
+21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;;
+21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;;
+21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;;
+21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;;
+21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;;
+21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;;
+21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;;
+21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;;
+21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
+21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;;
+21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;;
+21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;;
+21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;;
+2200;FOR ALL;Sm;0;ON;;;;;N;;;;;
+2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;;
+2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;;
+2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;;
+2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;;
+2205;EMPTY SET;Sm;0;ON;;;;;N;;;;;
+2206;INCREMENT;Sm;0;ON;;;;;N;;;;;
+2207;NABLA;Sm;0;ON;;;;;N;;;;;
+2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;;
+2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;;
+220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;;
+220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;;
+220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;;
+220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;;
+220E;END OF PROOF;Sm;0;ON;;;;;N;;;;;
+220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;;
+2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;;
+2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;;
+2212;MINUS SIGN;Sm;0;ES;;;;;N;;;;;
+2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;;
+2214;DOT PLUS;Sm;0;ON;;;;;N;;;;;
+2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;;
+2216;SET MINUS;Sm;0;ON;;;;;Y;;;;;
+2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;;
+2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;;
+2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;;
+221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;;
+221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;;
+221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;;
+221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;;
+221E;INFINITY;Sm;0;ON;;;;;N;;;;;
+221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;;
+2220;ANGLE;Sm;0;ON;;;;;Y;;;;;
+2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;;
+2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;;
+2223;DIVIDES;Sm;0;ON;;;;;N;;;;;
+2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;;
+2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;;
+2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;;
+2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;;
+2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;;
+2229;INTERSECTION;Sm;0;ON;;;;;N;;;;;
+222A;UNION;Sm;0;ON;;;;;N;;;;;
+222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+222C;DOUBLE INTEGRAL;Sm;0;ON;<compat> 222B 222B;;;;Y;;;;;
+222D;TRIPLE INTEGRAL;Sm;0;ON;<compat> 222B 222B 222B;;;;Y;;;;;
+222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+222F;SURFACE INTEGRAL;Sm;0;ON;<compat> 222E 222E;;;;Y;;;;;
+2230;VOLUME INTEGRAL;Sm;0;ON;<compat> 222E 222E 222E;;;;Y;;;;;
+2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+2234;THEREFORE;Sm;0;ON;;;;;N;;;;;
+2235;BECAUSE;Sm;0;ON;;;;;N;;;;;
+2236;RATIO;Sm;0;ON;;;;;N;;;;;
+2237;PROPORTION;Sm;0;ON;;;;;N;;;;;
+2238;DOT MINUS;Sm;0;ON;;;;;N;;;;;
+2239;EXCESS;Sm;0;ON;;;;;Y;;;;;
+223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;;
+223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;;
+223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
+223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;;;;
+223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;;
+223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;;
+2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;;
+2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;;
+2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;;
+2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;;
+2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;;
+2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;;
+224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;;
+224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;;
+224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;;
+224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;;
+2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;;
+2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;;
+2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;;
+2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;;
+2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;;
+2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;;
+2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;;
+2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;;
+2259;ESTIMATES;Sm;0;ON;;;;;N;;;;;
+225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;;
+225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;;
+225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;;
+225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;;
+225E;MEASURED BY;Sm;0;ON;;;;;N;;;;;
+225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;;
+2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;;
+2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;;
+2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;;
+2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;;
+2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;;
+2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;;
+2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;;
+2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;;
+2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;;
+226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;;
+226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;;
+226C;BETWEEN;Sm;0;ON;;;;;N;;;;;
+226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;N;;;;;
+226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;;
+226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;;
+2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;;
+2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;;
+2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;;
+2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;;
+2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;;
+2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;;
+2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;;
+2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;;
+2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;;
+2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;;
+227A;PRECEDES;Sm;0;ON;;;;;Y;;;;;
+227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;;
+227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
+227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
+2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;;
+2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;;
+2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;;
+2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;;
+2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;;
+2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;;
+2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;;
+2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;;
+228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;;
+228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;;
+228C;MULTISET;Sm;0;ON;;;;;Y;;;;;
+228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;;
+228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;;
+228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;;
+2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;;
+2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;;
+2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;;
+2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;;
+2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;;
+2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;;
+2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;;
+2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
+229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;;
+229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;;
+229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;;
+229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;;
+229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;;
+229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;;
+22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;;
+22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
+22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;;
+22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;;
+22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;;
+22A5;UP TACK;Sm;0;ON;;;;;N;;;;;
+22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;;
+22A7;MODELS;Sm;0;ON;;;;;Y;;;;;
+22A8;TRUE;Sm;0;ON;;;;;Y;;;;;
+22A9;FORCES;Sm;0;ON;;;;;Y;;;;;
+22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
+22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
+22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;;
+22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;;
+22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;;
+22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;;
+22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;;
+22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;;
+22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;;
+22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;;
+22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;;
+22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;;
+22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;;
+22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;;
+22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;;
+22BB;XOR;Sm;0;ON;;;;;N;;;;;
+22BC;NAND;Sm;0;ON;;;;;N;;;;;
+22BD;NOR;Sm;0;ON;;;;;N;;;;;
+22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;;
+22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;;
+22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;;
+22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;;
+22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;;
+22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;;
+22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;;
+22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
+22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;;
+22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;;
+22C8;BOWTIE;Sm;0;ON;;;;;N;;;;;
+22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
+22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
+22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
+22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;;
+22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;;
+22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;;
+22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;;
+22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;;
+22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;;
+22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;;
+22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;;
+22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;;
+22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;;
+22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;;
+22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;;
+22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;;
+22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;;
+22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;;
+22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;;
+22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;;
+22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;;
+22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;;
+22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;;
+22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;;
+22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;;
+22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;;
+22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;;
+22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;;
+22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;;
+22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
+22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;;
+22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;;
+22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;;
+22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;;
+22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;;
+22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;;
+22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;;
+22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;;
+22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;;
+22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
+22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
+22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
+22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
+22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
+22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
+22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
+22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;;
+22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
+22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
+22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
+22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
+22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
+22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;;
+2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;;
+2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;;
+2302;HOUSE;So;0;ON;;;;;N;;;;;
+2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;;
+2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;;
+2305;PROJECTIVE;So;0;ON;;;;;N;;;;;
+2306;PERSPECTIVE;So;0;ON;;;;;N;;;;;
+2307;WAVY LINE;So;0;ON;;;;;N;;;;;
+2308;LEFT CEILING;Sm;0;ON;;;;;Y;;;;;
+2309;RIGHT CEILING;Sm;0;ON;;;;;Y;;;;;
+230A;LEFT FLOOR;Sm;0;ON;;;;;Y;;;;;
+230B;RIGHT FLOOR;Sm;0;ON;;;;;Y;;;;;
+230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;;
+230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;;
+230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;;
+230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;;
+2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;;
+2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;;
+2312;ARC;So;0;ON;;;;;N;;;;;
+2313;SEGMENT;So;0;ON;;;;;N;;;;;
+2314;SECTOR;So;0;ON;;;;;N;;;;;
+2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;;
+2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;;
+2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;;
+2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;;
+2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;;
+231A;WATCH;So;0;ON;;;;;N;;;;;
+231B;HOURGLASS;So;0;ON;;;;;N;;;;;
+231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;;
+231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;;
+231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;;
+231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;;
+2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+2322;FROWN;So;0;ON;;;;;N;;;;;
+2323;SMILE;So;0;ON;;;;;N;;;;;
+2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;;
+2325;OPTION KEY;So;0;ON;;;;;N;;;;;
+2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;;
+2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;;
+2328;KEYBOARD;So;0;ON;;;;;N;;;;;
+2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;;
+232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;;
+232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;;
+232C;BENZENE RING;So;0;ON;;;;;N;;;;;
+232D;CYLINDRICITY;So;0;ON;;;;;N;;;;;
+232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;;
+232F;SYMMETRY;So;0;ON;;;;;N;;;;;
+2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;;
+2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;;
+2332;CONICAL TAPER;So;0;ON;;;;;N;;;;;
+2333;SLOPE;So;0;ON;;;;;N;;;;;
+2334;COUNTERBORE;So;0;ON;;;;;N;;;;;
+2335;COUNTERSINK;So;0;ON;;;;;N;;;;;
+2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;;
+2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;;
+2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;;
+2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;;
+233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;;
+233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;;
+233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;;
+233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;;
+233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;;
+233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;;
+2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;;
+2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;;
+2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;;
+2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;;
+2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;;
+2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;;
+2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;;
+2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;;
+2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;;
+2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;;
+234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;;;;
+234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;;
+234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;;
+234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;;
+234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;;;;
+234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;;
+2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;;
+2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;;;;
+2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;;
+2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;;
+2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;;
+2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;;;;
+2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;;
+2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;;
+2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;;
+2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;;
+235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;;
+235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;;
+235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;;
+235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;;
+235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;;
+235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;;
+2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;;
+2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;;;;
+2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;;
+2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;;
+2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;;
+2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;;
+2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;;
+2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;;
+2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;;
+2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;;
+236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;;
+236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;;
+236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;;
+236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;;
+236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;;
+236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;;
+2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;;
+2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;;
+2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;;
+2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;;
+2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;;
+2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;;
+2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;;
+2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;;
+2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;;
+2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;;
+237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;;
+237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;;
+237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;;
+237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;;
+237E;BELL SYMBOL;So;0;ON;;;;;N;;;;;
+237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;;
+2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;;
+2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;;
+2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;;
+2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;;
+2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;;
+2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;;
+2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;;
+2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;;
+2388;HELM SYMBOL;So;0;ON;;;;;N;;;;;
+2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;;;;
+238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;;;;
+238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;;;;
+238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;;
+238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;;
+238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;;
+238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;;
+2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;;
+2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;;
+2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;;
+2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;;
+2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;;
+2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;;
+2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;;
+2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;;
+2398;NEXT PAGE;So;0;ON;;;;;N;;;;;
+2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;;
+239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;;
+239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;;
+239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;;
+239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;;
+239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;;
+239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;;
+23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;;
+23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;;
+23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;;
+23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;;
+23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;;
+23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;;
+23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;;
+23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;;
+23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;;
+23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;;
+23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;;
+23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;;
+23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;;
+23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;;
+23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;;
+23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;;
+23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;;
+23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;;
+23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;;
+23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;;
+23B4;TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;;
+23B5;BOTTOM SQUARE BRACKET;So;0;ON;;;;;N;;;;;
+23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;;
+23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;;
+23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;;
+23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;;
+23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;;
+23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;;
+23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;;
+23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;;
+23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;;
+23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;;
+23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;;
+23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;;
+23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;;
+23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;;
+23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;;
+23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;;
+23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;;
+23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;;
+23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;;
+23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;;
+23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;;
+23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;;
+23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;;
+23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;;
+23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;;
+23CF;EJECT SYMBOL;So;0;ON;;;;;N;;;;;
+23D0;VERTICAL LINE EXTENSION;So;0;ON;;;;;N;;;;;
+23D1;METRICAL BREVE;So;0;ON;;;;;N;;;;;
+23D2;METRICAL LONG OVER SHORT;So;0;ON;;;;;N;;;;;
+23D3;METRICAL SHORT OVER LONG;So;0;ON;;;;;N;;;;;
+23D4;METRICAL LONG OVER TWO SHORTS;So;0;ON;;;;;N;;;;;
+23D5;METRICAL TWO SHORTS OVER LONG;So;0;ON;;;;;N;;;;;
+23D6;METRICAL TWO SHORTS JOINED;So;0;ON;;;;;N;;;;;
+23D7;METRICAL TRISEME;So;0;ON;;;;;N;;;;;
+23D8;METRICAL TETRASEME;So;0;ON;;;;;N;;;;;
+23D9;METRICAL PENTASEME;So;0;ON;;;;;N;;;;;
+23DA;EARTH GROUND;So;0;ON;;;;;N;;;;;
+23DB;FUSE;So;0;ON;;;;;N;;;;;
+23DC;TOP PARENTHESIS;Sm;0;ON;;;;;N;;;;;
+23DD;BOTTOM PARENTHESIS;Sm;0;ON;;;;;N;;;;;
+23DE;TOP CURLY BRACKET;Sm;0;ON;;;;;N;;;;;
+23DF;BOTTOM CURLY BRACKET;Sm;0;ON;;;;;N;;;;;
+23E0;TOP TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;;
+23E1;BOTTOM TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;;
+23E2;WHITE TRAPEZIUM;So;0;ON;;;;;N;;;;;
+23E3;BENZENE RING WITH CIRCLE;So;0;ON;;;;;N;;;;;
+23E4;STRAIGHTNESS;So;0;ON;;;;;N;;;;;
+23E5;FLATNESS;So;0;ON;;;;;N;;;;;
+23E6;AC CURRENT;So;0;ON;;;;;N;;;;;
+23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;;
+23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;;
+2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;;
+2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;;
+2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;;
+2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;;
+2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;;
+2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;;
+2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;;
+2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;;
+2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;;
+2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;;
+240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;;
+240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;;
+240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;;
+240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;;
+240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;;
+240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;;
+2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;;
+2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;;
+2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;;
+2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;;
+2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;;
+2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;;
+2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;;
+2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;;
+2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;;
+2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;;
+241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;;
+241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;;
+241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;;
+241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;;
+241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;;
+241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;;
+2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;;
+2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;;
+2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;;
+2423;OPEN BOX;So;0;ON;;;;;N;;;;;
+2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;;
+2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;;
+2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;;
+2440;OCR HOOK;So;0;ON;;;;;N;;;;;
+2441;OCR CHAIR;So;0;ON;;;;;N;;;;;
+2442;OCR FORK;So;0;ON;;;;;N;;;;;
+2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;;
+2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;;
+2445;OCR BOW TIE;So;0;ON;;;;;N;;;;;
+2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;;
+2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;;
+2448;OCR DASH;So;0;ON;;;;;N;;;;;
+2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;;
+244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;;
+2460;CIRCLED DIGIT ONE;No;0;ON;<circle> 0031;;1;1;N;;;;;
+2461;CIRCLED DIGIT TWO;No;0;ON;<circle> 0032;;2;2;N;;;;;
+2462;CIRCLED DIGIT THREE;No;0;ON;<circle> 0033;;3;3;N;;;;;
+2463;CIRCLED DIGIT FOUR;No;0;ON;<circle> 0034;;4;4;N;;;;;
+2464;CIRCLED DIGIT FIVE;No;0;ON;<circle> 0035;;5;5;N;;;;;
+2465;CIRCLED DIGIT SIX;No;0;ON;<circle> 0036;;6;6;N;;;;;
+2466;CIRCLED DIGIT SEVEN;No;0;ON;<circle> 0037;;7;7;N;;;;;
+2467;CIRCLED DIGIT EIGHT;No;0;ON;<circle> 0038;;8;8;N;;;;;
+2468;CIRCLED DIGIT NINE;No;0;ON;<circle> 0039;;9;9;N;;;;;
+2469;CIRCLED NUMBER TEN;No;0;ON;<circle> 0031 0030;;;10;N;;;;;
+246A;CIRCLED NUMBER ELEVEN;No;0;ON;<circle> 0031 0031;;;11;N;;;;;
+246B;CIRCLED NUMBER TWELVE;No;0;ON;<circle> 0031 0032;;;12;N;;;;;
+246C;CIRCLED NUMBER THIRTEEN;No;0;ON;<circle> 0031 0033;;;13;N;;;;;
+246D;CIRCLED NUMBER FOURTEEN;No;0;ON;<circle> 0031 0034;;;14;N;;;;;
+246E;CIRCLED NUMBER FIFTEEN;No;0;ON;<circle> 0031 0035;;;15;N;;;;;
+246F;CIRCLED NUMBER SIXTEEN;No;0;ON;<circle> 0031 0036;;;16;N;;;;;
+2470;CIRCLED NUMBER SEVENTEEN;No;0;ON;<circle> 0031 0037;;;17;N;;;;;
+2471;CIRCLED NUMBER EIGHTEEN;No;0;ON;<circle> 0031 0038;;;18;N;;;;;
+2472;CIRCLED NUMBER NINETEEN;No;0;ON;<circle> 0031 0039;;;19;N;;;;;
+2473;CIRCLED NUMBER TWENTY;No;0;ON;<circle> 0032 0030;;;20;N;;;;;
+2474;PARENTHESIZED DIGIT ONE;No;0;ON;<compat> 0028 0031 0029;;1;1;N;;;;;
+2475;PARENTHESIZED DIGIT TWO;No;0;ON;<compat> 0028 0032 0029;;2;2;N;;;;;
+2476;PARENTHESIZED DIGIT THREE;No;0;ON;<compat> 0028 0033 0029;;3;3;N;;;;;
+2477;PARENTHESIZED DIGIT FOUR;No;0;ON;<compat> 0028 0034 0029;;4;4;N;;;;;
+2478;PARENTHESIZED DIGIT FIVE;No;0;ON;<compat> 0028 0035 0029;;5;5;N;;;;;
+2479;PARENTHESIZED DIGIT SIX;No;0;ON;<compat> 0028 0036 0029;;6;6;N;;;;;
+247A;PARENTHESIZED DIGIT SEVEN;No;0;ON;<compat> 0028 0037 0029;;7;7;N;;;;;
+247B;PARENTHESIZED DIGIT EIGHT;No;0;ON;<compat> 0028 0038 0029;;8;8;N;;;;;
+247C;PARENTHESIZED DIGIT NINE;No;0;ON;<compat> 0028 0039 0029;;9;9;N;;;;;
+247D;PARENTHESIZED NUMBER TEN;No;0;ON;<compat> 0028 0031 0030 0029;;;10;N;;;;;
+247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON;<compat> 0028 0031 0031 0029;;;11;N;;;;;
+247F;PARENTHESIZED NUMBER TWELVE;No;0;ON;<compat> 0028 0031 0032 0029;;;12;N;;;;;
+2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON;<compat> 0028 0031 0033 0029;;;13;N;;;;;
+2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON;<compat> 0028 0031 0034 0029;;;14;N;;;;;
+2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON;<compat> 0028 0031 0035 0029;;;15;N;;;;;
+2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON;<compat> 0028 0031 0036 0029;;;16;N;;;;;
+2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON;<compat> 0028 0031 0037 0029;;;17;N;;;;;
+2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON;<compat> 0028 0031 0038 0029;;;18;N;;;;;
+2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON;<compat> 0028 0031 0039 0029;;;19;N;;;;;
+2487;PARENTHESIZED NUMBER TWENTY;No;0;ON;<compat> 0028 0032 0030 0029;;;20;N;;;;;
+2488;DIGIT ONE FULL STOP;No;0;EN;<compat> 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;;
+2489;DIGIT TWO FULL STOP;No;0;EN;<compat> 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;;
+248A;DIGIT THREE FULL STOP;No;0;EN;<compat> 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;;
+248B;DIGIT FOUR FULL STOP;No;0;EN;<compat> 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;;
+248C;DIGIT FIVE FULL STOP;No;0;EN;<compat> 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;;
+248D;DIGIT SIX FULL STOP;No;0;EN;<compat> 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;;
+248E;DIGIT SEVEN FULL STOP;No;0;EN;<compat> 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;;
+248F;DIGIT EIGHT FULL STOP;No;0;EN;<compat> 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;;
+2490;DIGIT NINE FULL STOP;No;0;EN;<compat> 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;;
+2491;NUMBER TEN FULL STOP;No;0;EN;<compat> 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;;
+2492;NUMBER ELEVEN FULL STOP;No;0;EN;<compat> 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;;
+2493;NUMBER TWELVE FULL STOP;No;0;EN;<compat> 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;;
+2494;NUMBER THIRTEEN FULL STOP;No;0;EN;<compat> 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;;
+2495;NUMBER FOURTEEN FULL STOP;No;0;EN;<compat> 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;;
+2496;NUMBER FIFTEEN FULL STOP;No;0;EN;<compat> 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;;
+2497;NUMBER SIXTEEN FULL STOP;No;0;EN;<compat> 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;;
+2498;NUMBER SEVENTEEN FULL STOP;No;0;EN;<compat> 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;;
+2499;NUMBER EIGHTEEN FULL STOP;No;0;EN;<compat> 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;;
+249A;NUMBER NINETEEN FULL STOP;No;0;EN;<compat> 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;;
+249B;NUMBER TWENTY FULL STOP;No;0;EN;<compat> 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;;
+249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L;<compat> 0028 0061 0029;;;;N;;;;;
+249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L;<compat> 0028 0062 0029;;;;N;;;;;
+249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L;<compat> 0028 0063 0029;;;;N;;;;;
+249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L;<compat> 0028 0064 0029;;;;N;;;;;
+24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L;<compat> 0028 0065 0029;;;;N;;;;;
+24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L;<compat> 0028 0066 0029;;;;N;;;;;
+24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L;<compat> 0028 0067 0029;;;;N;;;;;
+24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L;<compat> 0028 0068 0029;;;;N;;;;;
+24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L;<compat> 0028 0069 0029;;;;N;;;;;
+24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L;<compat> 0028 006A 0029;;;;N;;;;;
+24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L;<compat> 0028 006B 0029;;;;N;;;;;
+24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L;<compat> 0028 006C 0029;;;;N;;;;;
+24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L;<compat> 0028 006D 0029;;;;N;;;;;
+24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L;<compat> 0028 006E 0029;;;;N;;;;;
+24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L;<compat> 0028 006F 0029;;;;N;;;;;
+24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L;<compat> 0028 0070 0029;;;;N;;;;;
+24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L;<compat> 0028 0071 0029;;;;N;;;;;
+24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L;<compat> 0028 0072 0029;;;;N;;;;;
+24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L;<compat> 0028 0073 0029;;;;N;;;;;
+24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L;<compat> 0028 0074 0029;;;;N;;;;;
+24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L;<compat> 0028 0075 0029;;;;N;;;;;
+24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L;<compat> 0028 0076 0029;;;;N;;;;;
+24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L;<compat> 0028 0077 0029;;;;N;;;;;
+24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L;<compat> 0028 0078 0029;;;;N;;;;;
+24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L;<compat> 0028 0079 0029;;;;N;;;;;
+24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L;<compat> 0028 007A 0029;;;;N;;;;;
+24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L;<circle> 0041;;;;N;;;;24D0;
+24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L;<circle> 0042;;;;N;;;;24D1;
+24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;24D2;
+24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L;<circle> 0044;;;;N;;;;24D3;
+24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L;<circle> 0045;;;;N;;;;24D4;
+24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L;<circle> 0046;;;;N;;;;24D5;
+24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L;<circle> 0047;;;;N;;;;24D6;
+24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L;<circle> 0048;;;;N;;;;24D7;
+24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L;<circle> 0049;;;;N;;;;24D8;
+24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L;<circle> 004A;;;;N;;;;24D9;
+24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L;<circle> 004B;;;;N;;;;24DA;
+24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L;<circle> 004C;;;;N;;;;24DB;
+24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L;<circle> 004D;;;;N;;;;24DC;
+24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L;<circle> 004E;;;;N;;;;24DD;
+24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L;<circle> 004F;;;;N;;;;24DE;
+24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L;<circle> 0050;;;;N;;;;24DF;
+24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L;<circle> 0051;;;;N;;;;24E0;
+24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;24E1;
+24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L;<circle> 0053;;;;N;;;;24E2;
+24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L;<circle> 0054;;;;N;;;;24E3;
+24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L;<circle> 0055;;;;N;;;;24E4;
+24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L;<circle> 0056;;;;N;;;;24E5;
+24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L;<circle> 0057;;;;N;;;;24E6;
+24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L;<circle> 0058;;;;N;;;;24E7;
+24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L;<circle> 0059;;;;N;;;;24E8;
+24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L;<circle> 005A;;;;N;;;;24E9;
+24D0;CIRCLED LATIN SMALL LETTER A;So;0;L;<circle> 0061;;;;N;;;24B6;;24B6
+24D1;CIRCLED LATIN SMALL LETTER B;So;0;L;<circle> 0062;;;;N;;;24B7;;24B7
+24D2;CIRCLED LATIN SMALL LETTER C;So;0;L;<circle> 0063;;;;N;;;24B8;;24B8
+24D3;CIRCLED LATIN SMALL LETTER D;So;0;L;<circle> 0064;;;;N;;;24B9;;24B9
+24D4;CIRCLED LATIN SMALL LETTER E;So;0;L;<circle> 0065;;;;N;;;24BA;;24BA
+24D5;CIRCLED LATIN SMALL LETTER F;So;0;L;<circle> 0066;;;;N;;;24BB;;24BB
+24D6;CIRCLED LATIN SMALL LETTER G;So;0;L;<circle> 0067;;;;N;;;24BC;;24BC
+24D7;CIRCLED LATIN SMALL LETTER H;So;0;L;<circle> 0068;;;;N;;;24BD;;24BD
+24D8;CIRCLED LATIN SMALL LETTER I;So;0;L;<circle> 0069;;;;N;;;24BE;;24BE
+24D9;CIRCLED LATIN SMALL LETTER J;So;0;L;<circle> 006A;;;;N;;;24BF;;24BF
+24DA;CIRCLED LATIN SMALL LETTER K;So;0;L;<circle> 006B;;;;N;;;24C0;;24C0
+24DB;CIRCLED LATIN SMALL LETTER L;So;0;L;<circle> 006C;;;;N;;;24C1;;24C1
+24DC;CIRCLED LATIN SMALL LETTER M;So;0;L;<circle> 006D;;;;N;;;24C2;;24C2
+24DD;CIRCLED LATIN SMALL LETTER N;So;0;L;<circle> 006E;;;;N;;;24C3;;24C3
+24DE;CIRCLED LATIN SMALL LETTER O;So;0;L;<circle> 006F;;;;N;;;24C4;;24C4
+24DF;CIRCLED LATIN SMALL LETTER P;So;0;L;<circle> 0070;;;;N;;;24C5;;24C5
+24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L;<circle> 0071;;;;N;;;24C6;;24C6
+24E1;CIRCLED LATIN SMALL LETTER R;So;0;L;<circle> 0072;;;;N;;;24C7;;24C7
+24E2;CIRCLED LATIN SMALL LETTER S;So;0;L;<circle> 0073;;;;N;;;24C8;;24C8
+24E3;CIRCLED LATIN SMALL LETTER T;So;0;L;<circle> 0074;;;;N;;;24C9;;24C9
+24E4;CIRCLED LATIN SMALL LETTER U;So;0;L;<circle> 0075;;;;N;;;24CA;;24CA
+24E5;CIRCLED LATIN SMALL LETTER V;So;0;L;<circle> 0076;;;;N;;;24CB;;24CB
+24E6;CIRCLED LATIN SMALL LETTER W;So;0;L;<circle> 0077;;;;N;;;24CC;;24CC
+24E7;CIRCLED LATIN SMALL LETTER X;So;0;L;<circle> 0078;;;;N;;;24CD;;24CD
+24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L;<circle> 0079;;;;N;;;24CE;;24CE
+24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L;<circle> 007A;;;;N;;;24CF;;24CF
+24EA;CIRCLED DIGIT ZERO;No;0;ON;<circle> 0030;;0;0;N;;;;;
+24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;;
+24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;;
+24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;;
+24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;;
+24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;;
+24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;;
+24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;;
+24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;;
+24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;;
+24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;;
+24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;;
+24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;;
+24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;;
+24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;;
+24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;;
+24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;;
+24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;;
+24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;;
+24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;;
+24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;;
+24FF;NEGATIVE CIRCLED DIGIT ZERO;No;0;ON;;;0;0;N;;;;;
+2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;;
+2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;;
+2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;;
+2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;;
+2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;;
+2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;;
+2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;;
+2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;;
+2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;;
+2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;;
+250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;;
+250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;;
+250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;;
+250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;;
+250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;;
+250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;;
+2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;;
+2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;;
+2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;;
+2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;;
+2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;;
+2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;;
+2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;;
+2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;;
+2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;;
+2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;;
+251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;;
+251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;;
+251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;;
+251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;;
+251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;;
+251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;;
+2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;;
+2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;;
+2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;;
+2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;;
+2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;;
+2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;;
+2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;;
+2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;;
+2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;;
+2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;;
+252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;;
+252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;;
+252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;;
+252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;;
+252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;;
+252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;;
+2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;;
+2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;;
+2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;;
+2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;;
+2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;;
+2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;;
+2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;;
+2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;;
+2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;;
+2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;;
+253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;;
+253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;;
+253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;;
+253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;;
+253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;;
+253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;;
+2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;;
+2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;;
+2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;;
+2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;;
+2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;;
+2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;;
+2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;;
+2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;;
+2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;;
+2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;;
+254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;;
+254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;;
+254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;;
+254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;;
+254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;;
+254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;;
+2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;;
+2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;;
+2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;;
+2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;;
+2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;;
+2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;;
+2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;;
+2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;;
+2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;;
+2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;;
+255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;;
+255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;;
+255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;;
+255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;;
+255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;;
+255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;;
+2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;;
+2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;;
+2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;;
+2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;;
+2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;;
+2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;;
+2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;;
+2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;;
+2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;;
+2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;;
+256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;;
+256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;;
+256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;;
+256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;;
+256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;;
+256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;;
+2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;;
+2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;;
+2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;;
+2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;;
+2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;;
+2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;;
+2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;;
+2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;;
+2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;;
+2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;;
+257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;;
+257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;;
+257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;;
+257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;;
+257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;;
+257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;;
+2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;;
+2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
+2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;;
+2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
+2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;;
+2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
+2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;;
+2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
+2588;FULL BLOCK;So;0;ON;;;;;N;;;;;
+2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
+258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;;
+258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
+258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;;
+258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;;
+258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;;
+258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
+2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;;
+2591;LIGHT SHADE;So;0;ON;;;;;N;;;;;
+2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;;
+2593;DARK SHADE;So;0;ON;;;;;N;;;;;
+2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
+2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;;
+2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;;
+2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;;
+2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;;
+2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
+259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
+259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;;
+259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
+259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;;
+259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;;
+259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;;
+25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;;
+25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;;
+25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;;
+25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;;
+25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;;
+25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;;
+25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;;
+25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;;
+25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;;
+25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;;
+25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;;
+25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;;
+25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;;
+25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;;
+25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;;
+25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;;
+25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;;
+25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;;
+25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;;
+25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;;
+25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;;
+25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;;
+25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;;
+25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;;
+25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;;
+25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;;
+25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;;
+25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;;
+25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;;
+25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;;
+25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;;
+25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;;
+25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;;
+25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;;
+25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;;
+25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;;
+25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;;
+25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;;
+25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;;
+25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;;
+25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;;
+25C9;FISHEYE;So;0;ON;;;;;N;;;;;
+25CA;LOZENGE;So;0;ON;;;;;N;;;;;
+25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;;
+25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;;
+25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;;
+25CE;BULLSEYE;So;0;ON;;;;;N;;;;;
+25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;;
+25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;;
+25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;;
+25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;;
+25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;;
+25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;;
+25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;;
+25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;;
+25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;;
+25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;;
+25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;;
+25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;;
+25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;;
+25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
+25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
+25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
+25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;;
+25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;;
+25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;;
+25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;;
+25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;;
+25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;;
+25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;;
+25E6;WHITE BULLET;So;0;ON;;;;;N;;;;;
+25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;;
+25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;;
+25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
+25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
+25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;;
+25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;;
+25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;;
+25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;;
+25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;;
+25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
+25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
+25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
+25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
+25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
+25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;;
+25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
+25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;;
+25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;;
+25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;;
+25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;;
+25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;;
+25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;;
+25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;;
+25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;;
+25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;;
+2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;;
+2601;CLOUD;So;0;ON;;;;;N;;;;;
+2602;UMBRELLA;So;0;ON;;;;;N;;;;;
+2603;SNOWMAN;So;0;ON;;;;;N;;;;;
+2604;COMET;So;0;ON;;;;;N;;;;;
+2605;BLACK STAR;So;0;ON;;;;;N;;;;;
+2606;WHITE STAR;So;0;ON;;;;;N;;;;;
+2607;LIGHTNING;So;0;ON;;;;;N;;;;;
+2608;THUNDERSTORM;So;0;ON;;;;;N;;;;;
+2609;SUN;So;0;ON;;;;;N;;;;;
+260A;ASCENDING NODE;So;0;ON;;;;;N;;;;;
+260B;DESCENDING NODE;So;0;ON;;;;;N;;;;;
+260C;CONJUNCTION;So;0;ON;;;;;N;;;;;
+260D;OPPOSITION;So;0;ON;;;;;N;;;;;
+260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;;
+260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;;
+2610;BALLOT BOX;So;0;ON;;;;;N;;;;;
+2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;;
+2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;;
+2613;SALTIRE;So;0;ON;;;;;N;;;;;
+2614;UMBRELLA WITH RAIN DROPS;So;0;ON;;;;;N;;;;;
+2615;HOT BEVERAGE;So;0;ON;;;;;N;;;;;
+2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;;
+2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;;
+2618;SHAMROCK;So;0;ON;;;;;N;;;;;
+2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;;
+261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;;
+261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;;
+261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;;
+261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;;
+261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;;
+261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;;
+2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;;
+2621;CAUTION SIGN;So;0;ON;;;;;N;;;;;
+2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;;
+2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;;
+2624;CADUCEUS;So;0;ON;;;;;N;;;;;
+2625;ANKH;So;0;ON;;;;;N;;;;;
+2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;;
+2627;CHI RHO;So;0;ON;;;;;N;;;;;
+2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;;
+2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;;
+262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;;
+262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;;
+262C;ADI SHAKTI;So;0;ON;;;;;N;;;;;
+262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;;
+262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;;
+262F;YIN YANG;So;0;ON;;;;;N;;;;;
+2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;;
+2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;;
+2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;;
+2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;;
+2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;;
+2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;;
+2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;;
+2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;;
+2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;;
+2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;;
+263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;;
+263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;;
+263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;;
+263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;;
+263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;;
+263F;MERCURY;So;0;ON;;;;;N;;;;;
+2640;FEMALE SIGN;So;0;ON;;;;;N;;;;;
+2641;EARTH;So;0;ON;;;;;N;;;;;
+2642;MALE SIGN;So;0;ON;;;;;N;;;;;
+2643;JUPITER;So;0;ON;;;;;N;;;;;
+2644;SATURN;So;0;ON;;;;;N;;;;;
+2645;URANUS;So;0;ON;;;;;N;;;;;
+2646;NEPTUNE;So;0;ON;;;;;N;;;;;
+2647;PLUTO;So;0;ON;;;;;N;;;;;
+2648;ARIES;So;0;ON;;;;;N;;;;;
+2649;TAURUS;So;0;ON;;;;;N;;;;;
+264A;GEMINI;So;0;ON;;;;;N;;;;;
+264B;CANCER;So;0;ON;;;;;N;;;;;
+264C;LEO;So;0;ON;;;;;N;;;;;
+264D;VIRGO;So;0;ON;;;;;N;;;;;
+264E;LIBRA;So;0;ON;;;;;N;;;;;
+264F;SCORPIUS;So;0;ON;;;;;N;;;;;
+2650;SAGITTARIUS;So;0;ON;;;;;N;;;;;
+2651;CAPRICORN;So;0;ON;;;;;N;;;;;
+2652;AQUARIUS;So;0;ON;;;;;N;;;;;
+2653;PISCES;So;0;ON;;;;;N;;;;;
+2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;;
+2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;;
+2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;;
+2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;;
+2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;;
+2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;;
+265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;;
+265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;;
+265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;;
+265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;;
+265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;;
+265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;;
+2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;;
+2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;;
+2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;;
+2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;;
+2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;;
+2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;;
+2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;;
+2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;;
+2668;HOT SPRINGS;So;0;ON;;;;;N;;;;;
+2669;QUARTER NOTE;So;0;ON;;;;;N;;;;;
+266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;;
+266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;;
+266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;;
+266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;;
+266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;;
+266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;;
+2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;;
+2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;;
+2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;;
+2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;;;;
+2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;;;;
+2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;;;;
+2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;;;;
+2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;;;;
+2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;;;;
+2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;;;;
+267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;;
+267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;;
+267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;;
+267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;;
+267E;PERMANENT PAPER SIGN;So;0;ON;;;;;N;;;;;
+267F;WHEELCHAIR SYMBOL;So;0;ON;;;;;N;;;;;
+2680;DIE FACE-1;So;0;ON;;;;;N;;;;;
+2681;DIE FACE-2;So;0;ON;;;;;N;;;;;
+2682;DIE FACE-3;So;0;ON;;;;;N;;;;;
+2683;DIE FACE-4;So;0;ON;;;;;N;;;;;
+2684;DIE FACE-5;So;0;ON;;;;;N;;;;;
+2685;DIE FACE-6;So;0;ON;;;;;N;;;;;
+2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;;
+2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;;
+2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;;
+2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;;
+268A;MONOGRAM FOR YANG;So;0;ON;;;;;N;;;;;
+268B;MONOGRAM FOR YIN;So;0;ON;;;;;N;;;;;
+268C;DIGRAM FOR GREATER YANG;So;0;ON;;;;;N;;;;;
+268D;DIGRAM FOR LESSER YIN;So;0;ON;;;;;N;;;;;
+268E;DIGRAM FOR LESSER YANG;So;0;ON;;;;;N;;;;;
+268F;DIGRAM FOR GREATER YIN;So;0;ON;;;;;N;;;;;
+2690;WHITE FLAG;So;0;ON;;;;;N;;;;;
+2691;BLACK FLAG;So;0;ON;;;;;N;;;;;
+2692;HAMMER AND PICK;So;0;ON;;;;;N;;;;;
+2693;ANCHOR;So;0;ON;;;;;N;;;;;
+2694;CROSSED SWORDS;So;0;ON;;;;;N;;;;;
+2695;STAFF OF AESCULAPIUS;So;0;ON;;;;;N;;;;;
+2696;SCALES;So;0;ON;;;;;N;;;;;
+2697;ALEMBIC;So;0;ON;;;;;N;;;;;
+2698;FLOWER;So;0;ON;;;;;N;;;;;
+2699;GEAR;So;0;ON;;;;;N;;;;;
+269A;STAFF OF HERMES;So;0;ON;;;;;N;;;;;
+269B;ATOM SYMBOL;So;0;ON;;;;;N;;;;;
+269C;FLEUR-DE-LIS;So;0;ON;;;;;N;;;;;
+269D;OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;;
+269E;THREE LINES CONVERGING RIGHT;So;0;ON;;;;;N;;;;;
+269F;THREE LINES CONVERGING LEFT;So;0;ON;;;;;N;;;;;
+26A0;WARNING SIGN;So;0;ON;;;;;N;;;;;
+26A1;HIGH VOLTAGE SIGN;So;0;ON;;;;;N;;;;;
+26A2;DOUBLED FEMALE SIGN;So;0;ON;;;;;N;;;;;
+26A3;DOUBLED MALE SIGN;So;0;ON;;;;;N;;;;;
+26A4;INTERLOCKED FEMALE AND MALE SIGN;So;0;ON;;;;;N;;;;;
+26A5;MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;;
+26A6;MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;;
+26A7;MALE WITH STROKE AND MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;;
+26A8;VERTICAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;;
+26A9;HORIZONTAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;;
+26AA;MEDIUM WHITE CIRCLE;So;0;ON;;;;;N;;;;;
+26AB;MEDIUM BLACK CIRCLE;So;0;ON;;;;;N;;;;;
+26AC;MEDIUM SMALL WHITE CIRCLE;So;0;L;;;;;N;;;;;
+26AD;MARRIAGE SYMBOL;So;0;ON;;;;;N;;;;;
+26AE;DIVORCE SYMBOL;So;0;ON;;;;;N;;;;;
+26AF;UNMARRIED PARTNERSHIP SYMBOL;So;0;ON;;;;;N;;;;;
+26B0;COFFIN;So;0;ON;;;;;N;;;;;
+26B1;FUNERAL URN;So;0;ON;;;;;N;;;;;
+26B2;NEUTER;So;0;ON;;;;;N;;;;;
+26B3;CERES;So;0;ON;;;;;N;;;;;
+26B4;PALLAS;So;0;ON;;;;;N;;;;;
+26B5;JUNO;So;0;ON;;;;;N;;;;;
+26B6;VESTA;So;0;ON;;;;;N;;;;;
+26B7;CHIRON;So;0;ON;;;;;N;;;;;
+26B8;BLACK MOON LILITH;So;0;ON;;;;;N;;;;;
+26B9;SEXTILE;So;0;ON;;;;;N;;;;;
+26BA;SEMISEXTILE;So;0;ON;;;;;N;;;;;
+26BB;QUINCUNX;So;0;ON;;;;;N;;;;;
+26BC;SESQUIQUADRATE;So;0;ON;;;;;N;;;;;
+26BD;SOCCER BALL;So;0;ON;;;;;N;;;;;
+26BE;BASEBALL;So;0;ON;;;;;N;;;;;
+26BF;SQUARED KEY;So;0;ON;;;;;N;;;;;
+26C0;WHITE DRAUGHTS MAN;So;0;ON;;;;;N;;;;;
+26C1;WHITE DRAUGHTS KING;So;0;ON;;;;;N;;;;;
+26C2;BLACK DRAUGHTS MAN;So;0;ON;;;;;N;;;;;
+26C3;BLACK DRAUGHTS KING;So;0;ON;;;;;N;;;;;
+26C4;SNOWMAN WITHOUT SNOW;So;0;ON;;;;;N;;;;;
+26C5;SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;;
+26C6;RAIN;So;0;ON;;;;;N;;;;;
+26C7;BLACK SNOWMAN;So;0;ON;;;;;N;;;;;
+26C8;THUNDER CLOUD AND RAIN;So;0;ON;;;;;N;;;;;
+26C9;TURNED WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;;
+26CA;TURNED BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;;
+26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;;
+26CC;CROSSING LANES;So;0;ON;;;;;N;;;;;
+26CD;DISABLED CAR;So;0;ON;;;;;N;;;;;
+26CF;PICK;So;0;ON;;;;;N;;;;;
+26D0;CAR SLIDING;So;0;ON;;;;;N;;;;;
+26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;;
+26D2;CIRCLED CROSSING LANES;So;0;ON;;;;;N;;;;;
+26D3;CHAINS;So;0;ON;;;;;N;;;;;
+26D4;NO ENTRY;So;0;ON;;;;;N;;;;;
+26D5;ALTERNATE ONE-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;;
+26D6;BLACK TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;;
+26D7;WHITE TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;;
+26D8;BLACK LEFT LANE MERGE;So;0;ON;;;;;N;;;;;
+26D9;WHITE LEFT LANE MERGE;So;0;ON;;;;;N;;;;;
+26DA;DRIVE SLOW SIGN;So;0;ON;;;;;N;;;;;
+26DB;HEAVY WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;;
+26DC;LEFT CLOSED ENTRY;So;0;ON;;;;;N;;;;;
+26DD;SQUARED SALTIRE;So;0;ON;;;;;N;;;;;
+26DE;FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE;So;0;ON;;;;;N;;;;;
+26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;;
+26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;;
+26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;;
+26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;;
+26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;;
+26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;;
+26EA;CHURCH;So;0;ON;;;;;N;;;;;
+26EB;CASTLE;So;0;ON;;;;;N;;;;;
+26EC;HISTORIC SITE;So;0;ON;;;;;N;;;;;
+26ED;GEAR WITHOUT HUB;So;0;ON;;;;;N;;;;;
+26EE;GEAR WITH HANDLES;So;0;ON;;;;;N;;;;;
+26EF;MAP SYMBOL FOR LIGHTHOUSE;So;0;ON;;;;;N;;;;;
+26F0;MOUNTAIN;So;0;ON;;;;;N;;;;;
+26F1;UMBRELLA ON GROUND;So;0;ON;;;;;N;;;;;
+26F2;FOUNTAIN;So;0;ON;;;;;N;;;;;
+26F3;FLAG IN HOLE;So;0;ON;;;;;N;;;;;
+26F4;FERRY;So;0;ON;;;;;N;;;;;
+26F5;SAILBOAT;So;0;ON;;;;;N;;;;;
+26F6;SQUARE FOUR CORNERS;So;0;ON;;;;;N;;;;;
+26F7;SKIER;So;0;ON;;;;;N;;;;;
+26F8;ICE SKATE;So;0;ON;;;;;N;;;;;
+26F9;PERSON WITH BALL;So;0;ON;;;;;N;;;;;
+26FA;TENT;So;0;ON;;;;;N;;;;;
+26FB;JAPANESE BANK SYMBOL;So;0;ON;;;;;N;;;;;
+26FC;HEADSTONE GRAVEYARD SYMBOL;So;0;ON;;;;;N;;;;;
+26FD;FUEL PUMP;So;0;ON;;;;;N;;;;;
+26FE;CUP ON BLACK SQUARE;So;0;ON;;;;;N;;;;;
+26FF;WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE;So;0;ON;;;;;N;;;;;
+2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;;
+2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;;
+2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;;
+2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;;
+2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;;
+2707;TAPE DRIVE;So;0;ON;;;;;N;;;;;
+2708;AIRPLANE;So;0;ON;;;;;N;;;;;
+2709;ENVELOPE;So;0;ON;;;;;N;;;;;
+270C;VICTORY HAND;So;0;ON;;;;;N;;;;;
+270D;WRITING HAND;So;0;ON;;;;;N;;;;;
+270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;;
+270F;PENCIL;So;0;ON;;;;;N;;;;;
+2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;;
+2711;WHITE NIB;So;0;ON;;;;;N;;;;;
+2712;BLACK NIB;So;0;ON;;;;;N;;;;;
+2713;CHECK MARK;So;0;ON;;;;;N;;;;;
+2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;;
+2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;;
+2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;;
+2717;BALLOT X;So;0;ON;;;;;N;;;;;
+2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;;
+2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;;
+271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;;
+271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;;
+271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;;
+271D;LATIN CROSS;So;0;ON;;;;;N;;;;;
+271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;;
+271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;;
+2720;MALTESE CROSS;So;0;ON;;;;;N;;;;;
+2721;STAR OF DAVID;So;0;ON;;;;;N;;;;;
+2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;;
+2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;;
+2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;;
+272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;;
+272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;;
+272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;;
+272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;;
+272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;;
+272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;;
+2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;;
+2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;;
+2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;;
+2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;;
+2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;;
+2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;;
+2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;;
+2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;;
+2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;;
+273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;;
+273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;;
+273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;;
+273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;;
+2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;;
+2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;;
+2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;;
+2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;;
+2744;SNOWFLAKE;So;0;ON;;;;;N;;;;;
+2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;;
+2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;;
+2747;SPARKLE;So;0;ON;;;;;N;;;;;
+2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;;
+2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;;
+274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;;
+274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;;
+274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;;
+274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
+2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
+2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
+2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;;
+2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;;
+2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;;
+2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;;
+2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;;
+275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;;
+275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
+275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
+275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
+275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
+2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;;
+2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
+2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;;
+2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;;
+2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;;
+2766;FLORAL HEART;So;0;ON;;;;;N;;;;;
+2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;;
+2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;;
+2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;;
+276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;;
+276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;;
+276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
+276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
+276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;;
+276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;;
+2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
+2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
+2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
+2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
+2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;;
+2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;;
+2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;;
+2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;;
+2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;;
+2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;;
+277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;;
+277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;;
+277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;;
+277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;;
+277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;;
+277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;;
+2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;;
+2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;;
+2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;;
+2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;;
+2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;;
+2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;;
+2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;;
+2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;;
+2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;;
+2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;;
+278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;;
+278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;;
+278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;;
+278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;;
+278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;;
+278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;;
+2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;;
+2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;;
+2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;;
+2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;;
+2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;;
+2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;;
+2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;;
+279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;;
+279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;;
+279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;;
+279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;;
+279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;;
+279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;;
+27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;;
+27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;;
+27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;;
+27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;;
+27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;;
+27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;;
+27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;;
+27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;;
+27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;;
+27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;;
+27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;;
+27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;;
+27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;;
+27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
+27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
+27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
+27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;;
+27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;;
+27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;;
+27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;;
+27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;;
+27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;;
+27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;;
+27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;;
+27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;;
+27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;;
+27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;;
+27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;;
+27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;;
+27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;;
+27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;;
+27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;;
+27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;;
+27C3;OPEN SUBSET;Sm;0;ON;;;;;Y;;;;;
+27C4;OPEN SUPERSET;Sm;0;ON;;;;;Y;;;;;
+27C5;LEFT S-SHAPED BAG DELIMITER;Ps;0;ON;;;;;Y;;;;;
+27C6;RIGHT S-SHAPED BAG DELIMITER;Pe;0;ON;;;;;Y;;;;;
+27C7;OR WITH DOT INSIDE;Sm;0;ON;;;;;N;;;;;
+27C8;REVERSE SOLIDUS PRECEDING SUBSET;Sm;0;ON;;;;;Y;;;;;
+27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;;
+27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
+27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;;
+27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;;
+27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;;
+27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;;
+27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;;
+27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;;
+27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;;
+27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;;
+27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;;
+27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;;
+27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;;
+27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;;
+27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;;
+27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;;
+27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;;
+27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;;
+27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
+27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;;
+27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;;
+27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
+27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
+27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
+27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;;
+27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;;
+27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;;
+27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;;
+27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;;
+27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;;
+27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;;
+27EC;MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;;
+27ED;MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;;
+27EE;MATHEMATICAL LEFT FLATTENED PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
+27EF;MATHEMATICAL RIGHT FLATTENED PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
+27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;;
+27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;;
+27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
+27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
+27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;;
+27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;;
+27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
+27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
+27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;;
+27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;;
+2800;BRAILLE PATTERN BLANK;So;0;L;;;;;N;;;;;
+2801;BRAILLE PATTERN DOTS-1;So;0;L;;;;;N;;;;;
+2802;BRAILLE PATTERN DOTS-2;So;0;L;;;;;N;;;;;
+2803;BRAILLE PATTERN DOTS-12;So;0;L;;;;;N;;;;;
+2804;BRAILLE PATTERN DOTS-3;So;0;L;;;;;N;;;;;
+2805;BRAILLE PATTERN DOTS-13;So;0;L;;;;;N;;;;;
+2806;BRAILLE PATTERN DOTS-23;So;0;L;;;;;N;;;;;
+2807;BRAILLE PATTERN DOTS-123;So;0;L;;;;;N;;;;;
+2808;BRAILLE PATTERN DOTS-4;So;0;L;;;;;N;;;;;
+2809;BRAILLE PATTERN DOTS-14;So;0;L;;;;;N;;;;;
+280A;BRAILLE PATTERN DOTS-24;So;0;L;;;;;N;;;;;
+280B;BRAILLE PATTERN DOTS-124;So;0;L;;;;;N;;;;;
+280C;BRAILLE PATTERN DOTS-34;So;0;L;;;;;N;;;;;
+280D;BRAILLE PATTERN DOTS-134;So;0;L;;;;;N;;;;;
+280E;BRAILLE PATTERN DOTS-234;So;0;L;;;;;N;;;;;
+280F;BRAILLE PATTERN DOTS-1234;So;0;L;;;;;N;;;;;
+2810;BRAILLE PATTERN DOTS-5;So;0;L;;;;;N;;;;;
+2811;BRAILLE PATTERN DOTS-15;So;0;L;;;;;N;;;;;
+2812;BRAILLE PATTERN DOTS-25;So;0;L;;;;;N;;;;;
+2813;BRAILLE PATTERN DOTS-125;So;0;L;;;;;N;;;;;
+2814;BRAILLE PATTERN DOTS-35;So;0;L;;;;;N;;;;;
+2815;BRAILLE PATTERN DOTS-135;So;0;L;;;;;N;;;;;
+2816;BRAILLE PATTERN DOTS-235;So;0;L;;;;;N;;;;;
+2817;BRAILLE PATTERN DOTS-1235;So;0;L;;;;;N;;;;;
+2818;BRAILLE PATTERN DOTS-45;So;0;L;;;;;N;;;;;
+2819;BRAILLE PATTERN DOTS-145;So;0;L;;;;;N;;;;;
+281A;BRAILLE PATTERN DOTS-245;So;0;L;;;;;N;;;;;
+281B;BRAILLE PATTERN DOTS-1245;So;0;L;;;;;N;;;;;
+281C;BRAILLE PATTERN DOTS-345;So;0;L;;;;;N;;;;;
+281D;BRAILLE PATTERN DOTS-1345;So;0;L;;;;;N;;;;;
+281E;BRAILLE PATTERN DOTS-2345;So;0;L;;;;;N;;;;;
+281F;BRAILLE PATTERN DOTS-12345;So;0;L;;;;;N;;;;;
+2820;BRAILLE PATTERN DOTS-6;So;0;L;;;;;N;;;;;
+2821;BRAILLE PATTERN DOTS-16;So;0;L;;;;;N;;;;;
+2822;BRAILLE PATTERN DOTS-26;So;0;L;;;;;N;;;;;
+2823;BRAILLE PATTERN DOTS-126;So;0;L;;;;;N;;;;;
+2824;BRAILLE PATTERN DOTS-36;So;0;L;;;;;N;;;;;
+2825;BRAILLE PATTERN DOTS-136;So;0;L;;;;;N;;;;;
+2826;BRAILLE PATTERN DOTS-236;So;0;L;;;;;N;;;;;
+2827;BRAILLE PATTERN DOTS-1236;So;0;L;;;;;N;;;;;
+2828;BRAILLE PATTERN DOTS-46;So;0;L;;;;;N;;;;;
+2829;BRAILLE PATTERN DOTS-146;So;0;L;;;;;N;;;;;
+282A;BRAILLE PATTERN DOTS-246;So;0;L;;;;;N;;;;;
+282B;BRAILLE PATTERN DOTS-1246;So;0;L;;;;;N;;;;;
+282C;BRAILLE PATTERN DOTS-346;So;0;L;;;;;N;;;;;
+282D;BRAILLE PATTERN DOTS-1346;So;0;L;;;;;N;;;;;
+282E;BRAILLE PATTERN DOTS-2346;So;0;L;;;;;N;;;;;
+282F;BRAILLE PATTERN DOTS-12346;So;0;L;;;;;N;;;;;
+2830;BRAILLE PATTERN DOTS-56;So;0;L;;;;;N;;;;;
+2831;BRAILLE PATTERN DOTS-156;So;0;L;;;;;N;;;;;
+2832;BRAILLE PATTERN DOTS-256;So;0;L;;;;;N;;;;;
+2833;BRAILLE PATTERN DOTS-1256;So;0;L;;;;;N;;;;;
+2834;BRAILLE PATTERN DOTS-356;So;0;L;;;;;N;;;;;
+2835;BRAILLE PATTERN DOTS-1356;So;0;L;;;;;N;;;;;
+2836;BRAILLE PATTERN DOTS-2356;So;0;L;;;;;N;;;;;
+2837;BRAILLE PATTERN DOTS-12356;So;0;L;;;;;N;;;;;
+2838;BRAILLE PATTERN DOTS-456;So;0;L;;;;;N;;;;;
+2839;BRAILLE PATTERN DOTS-1456;So;0;L;;;;;N;;;;;
+283A;BRAILLE PATTERN DOTS-2456;So;0;L;;;;;N;;;;;
+283B;BRAILLE PATTERN DOTS-12456;So;0;L;;;;;N;;;;;
+283C;BRAILLE PATTERN DOTS-3456;So;0;L;;;;;N;;;;;
+283D;BRAILLE PATTERN DOTS-13456;So;0;L;;;;;N;;;;;
+283E;BRAILLE PATTERN DOTS-23456;So;0;L;;;;;N;;;;;
+283F;BRAILLE PATTERN DOTS-123456;So;0;L;;;;;N;;;;;
+2840;BRAILLE PATTERN DOTS-7;So;0;L;;;;;N;;;;;
+2841;BRAILLE PATTERN DOTS-17;So;0;L;;;;;N;;;;;
+2842;BRAILLE PATTERN DOTS-27;So;0;L;;;;;N;;;;;
+2843;BRAILLE PATTERN DOTS-127;So;0;L;;;;;N;;;;;
+2844;BRAILLE PATTERN DOTS-37;So;0;L;;;;;N;;;;;
+2845;BRAILLE PATTERN DOTS-137;So;0;L;;;;;N;;;;;
+2846;BRAILLE PATTERN DOTS-237;So;0;L;;;;;N;;;;;
+2847;BRAILLE PATTERN DOTS-1237;So;0;L;;;;;N;;;;;
+2848;BRAILLE PATTERN DOTS-47;So;0;L;;;;;N;;;;;
+2849;BRAILLE PATTERN DOTS-147;So;0;L;;;;;N;;;;;
+284A;BRAILLE PATTERN DOTS-247;So;0;L;;;;;N;;;;;
+284B;BRAILLE PATTERN DOTS-1247;So;0;L;;;;;N;;;;;
+284C;BRAILLE PATTERN DOTS-347;So;0;L;;;;;N;;;;;
+284D;BRAILLE PATTERN DOTS-1347;So;0;L;;;;;N;;;;;
+284E;BRAILLE PATTERN DOTS-2347;So;0;L;;;;;N;;;;;
+284F;BRAILLE PATTERN DOTS-12347;So;0;L;;;;;N;;;;;
+2850;BRAILLE PATTERN DOTS-57;So;0;L;;;;;N;;;;;
+2851;BRAILLE PATTERN DOTS-157;So;0;L;;;;;N;;;;;
+2852;BRAILLE PATTERN DOTS-257;So;0;L;;;;;N;;;;;
+2853;BRAILLE PATTERN DOTS-1257;So;0;L;;;;;N;;;;;
+2854;BRAILLE PATTERN DOTS-357;So;0;L;;;;;N;;;;;
+2855;BRAILLE PATTERN DOTS-1357;So;0;L;;;;;N;;;;;
+2856;BRAILLE PATTERN DOTS-2357;So;0;L;;;;;N;;;;;
+2857;BRAILLE PATTERN DOTS-12357;So;0;L;;;;;N;;;;;
+2858;BRAILLE PATTERN DOTS-457;So;0;L;;;;;N;;;;;
+2859;BRAILLE PATTERN DOTS-1457;So;0;L;;;;;N;;;;;
+285A;BRAILLE PATTERN DOTS-2457;So;0;L;;;;;N;;;;;
+285B;BRAILLE PATTERN DOTS-12457;So;0;L;;;;;N;;;;;
+285C;BRAILLE PATTERN DOTS-3457;So;0;L;;;;;N;;;;;
+285D;BRAILLE PATTERN DOTS-13457;So;0;L;;;;;N;;;;;
+285E;BRAILLE PATTERN DOTS-23457;So;0;L;;;;;N;;;;;
+285F;BRAILLE PATTERN DOTS-123457;So;0;L;;;;;N;;;;;
+2860;BRAILLE PATTERN DOTS-67;So;0;L;;;;;N;;;;;
+2861;BRAILLE PATTERN DOTS-167;So;0;L;;;;;N;;;;;
+2862;BRAILLE PATTERN DOTS-267;So;0;L;;;;;N;;;;;
+2863;BRAILLE PATTERN DOTS-1267;So;0;L;;;;;N;;;;;
+2864;BRAILLE PATTERN DOTS-367;So;0;L;;;;;N;;;;;
+2865;BRAILLE PATTERN DOTS-1367;So;0;L;;;;;N;;;;;
+2866;BRAILLE PATTERN DOTS-2367;So;0;L;;;;;N;;;;;
+2867;BRAILLE PATTERN DOTS-12367;So;0;L;;;;;N;;;;;
+2868;BRAILLE PATTERN DOTS-467;So;0;L;;;;;N;;;;;
+2869;BRAILLE PATTERN DOTS-1467;So;0;L;;;;;N;;;;;
+286A;BRAILLE PATTERN DOTS-2467;So;0;L;;;;;N;;;;;
+286B;BRAILLE PATTERN DOTS-12467;So;0;L;;;;;N;;;;;
+286C;BRAILLE PATTERN DOTS-3467;So;0;L;;;;;N;;;;;
+286D;BRAILLE PATTERN DOTS-13467;So;0;L;;;;;N;;;;;
+286E;BRAILLE PATTERN DOTS-23467;So;0;L;;;;;N;;;;;
+286F;BRAILLE PATTERN DOTS-123467;So;0;L;;;;;N;;;;;
+2870;BRAILLE PATTERN DOTS-567;So;0;L;;;;;N;;;;;
+2871;BRAILLE PATTERN DOTS-1567;So;0;L;;;;;N;;;;;
+2872;BRAILLE PATTERN DOTS-2567;So;0;L;;;;;N;;;;;
+2873;BRAILLE PATTERN DOTS-12567;So;0;L;;;;;N;;;;;
+2874;BRAILLE PATTERN DOTS-3567;So;0;L;;;;;N;;;;;
+2875;BRAILLE PATTERN DOTS-13567;So;0;L;;;;;N;;;;;
+2876;BRAILLE PATTERN DOTS-23567;So;0;L;;;;;N;;;;;
+2877;BRAILLE PATTERN DOTS-123567;So;0;L;;;;;N;;;;;
+2878;BRAILLE PATTERN DOTS-4567;So;0;L;;;;;N;;;;;
+2879;BRAILLE PATTERN DOTS-14567;So;0;L;;;;;N;;;;;
+287A;BRAILLE PATTERN DOTS-24567;So;0;L;;;;;N;;;;;
+287B;BRAILLE PATTERN DOTS-124567;So;0;L;;;;;N;;;;;
+287C;BRAILLE PATTERN DOTS-34567;So;0;L;;;;;N;;;;;
+287D;BRAILLE PATTERN DOTS-134567;So;0;L;;;;;N;;;;;
+287E;BRAILLE PATTERN DOTS-234567;So;0;L;;;;;N;;;;;
+287F;BRAILLE PATTERN DOTS-1234567;So;0;L;;;;;N;;;;;
+2880;BRAILLE PATTERN DOTS-8;So;0;L;;;;;N;;;;;
+2881;BRAILLE PATTERN DOTS-18;So;0;L;;;;;N;;;;;
+2882;BRAILLE PATTERN DOTS-28;So;0;L;;;;;N;;;;;
+2883;BRAILLE PATTERN DOTS-128;So;0;L;;;;;N;;;;;
+2884;BRAILLE PATTERN DOTS-38;So;0;L;;;;;N;;;;;
+2885;BRAILLE PATTERN DOTS-138;So;0;L;;;;;N;;;;;
+2886;BRAILLE PATTERN DOTS-238;So;0;L;;;;;N;;;;;
+2887;BRAILLE PATTERN DOTS-1238;So;0;L;;;;;N;;;;;
+2888;BRAILLE PATTERN DOTS-48;So;0;L;;;;;N;;;;;
+2889;BRAILLE PATTERN DOTS-148;So;0;L;;;;;N;;;;;
+288A;BRAILLE PATTERN DOTS-248;So;0;L;;;;;N;;;;;
+288B;BRAILLE PATTERN DOTS-1248;So;0;L;;;;;N;;;;;
+288C;BRAILLE PATTERN DOTS-348;So;0;L;;;;;N;;;;;
+288D;BRAILLE PATTERN DOTS-1348;So;0;L;;;;;N;;;;;
+288E;BRAILLE PATTERN DOTS-2348;So;0;L;;;;;N;;;;;
+288F;BRAILLE PATTERN DOTS-12348;So;0;L;;;;;N;;;;;
+2890;BRAILLE PATTERN DOTS-58;So;0;L;;;;;N;;;;;
+2891;BRAILLE PATTERN DOTS-158;So;0;L;;;;;N;;;;;
+2892;BRAILLE PATTERN DOTS-258;So;0;L;;;;;N;;;;;
+2893;BRAILLE PATTERN DOTS-1258;So;0;L;;;;;N;;;;;
+2894;BRAILLE PATTERN DOTS-358;So;0;L;;;;;N;;;;;
+2895;BRAILLE PATTERN DOTS-1358;So;0;L;;;;;N;;;;;
+2896;BRAILLE PATTERN DOTS-2358;So;0;L;;;;;N;;;;;
+2897;BRAILLE PATTERN DOTS-12358;So;0;L;;;;;N;;;;;
+2898;BRAILLE PATTERN DOTS-458;So;0;L;;;;;N;;;;;
+2899;BRAILLE PATTERN DOTS-1458;So;0;L;;;;;N;;;;;
+289A;BRAILLE PATTERN DOTS-2458;So;0;L;;;;;N;;;;;
+289B;BRAILLE PATTERN DOTS-12458;So;0;L;;;;;N;;;;;
+289C;BRAILLE PATTERN DOTS-3458;So;0;L;;;;;N;;;;;
+289D;BRAILLE PATTERN DOTS-13458;So;0;L;;;;;N;;;;;
+289E;BRAILLE PATTERN DOTS-23458;So;0;L;;;;;N;;;;;
+289F;BRAILLE PATTERN DOTS-123458;So;0;L;;;;;N;;;;;
+28A0;BRAILLE PATTERN DOTS-68;So;0;L;;;;;N;;;;;
+28A1;BRAILLE PATTERN DOTS-168;So;0;L;;;;;N;;;;;
+28A2;BRAILLE PATTERN DOTS-268;So;0;L;;;;;N;;;;;
+28A3;BRAILLE PATTERN DOTS-1268;So;0;L;;;;;N;;;;;
+28A4;BRAILLE PATTERN DOTS-368;So;0;L;;;;;N;;;;;
+28A5;BRAILLE PATTERN DOTS-1368;So;0;L;;;;;N;;;;;
+28A6;BRAILLE PATTERN DOTS-2368;So;0;L;;;;;N;;;;;
+28A7;BRAILLE PATTERN DOTS-12368;So;0;L;;;;;N;;;;;
+28A8;BRAILLE PATTERN DOTS-468;So;0;L;;;;;N;;;;;
+28A9;BRAILLE PATTERN DOTS-1468;So;0;L;;;;;N;;;;;
+28AA;BRAILLE PATTERN DOTS-2468;So;0;L;;;;;N;;;;;
+28AB;BRAILLE PATTERN DOTS-12468;So;0;L;;;;;N;;;;;
+28AC;BRAILLE PATTERN DOTS-3468;So;0;L;;;;;N;;;;;
+28AD;BRAILLE PATTERN DOTS-13468;So;0;L;;;;;N;;;;;
+28AE;BRAILLE PATTERN DOTS-23468;So;0;L;;;;;N;;;;;
+28AF;BRAILLE PATTERN DOTS-123468;So;0;L;;;;;N;;;;;
+28B0;BRAILLE PATTERN DOTS-568;So;0;L;;;;;N;;;;;
+28B1;BRAILLE PATTERN DOTS-1568;So;0;L;;;;;N;;;;;
+28B2;BRAILLE PATTERN DOTS-2568;So;0;L;;;;;N;;;;;
+28B3;BRAILLE PATTERN DOTS-12568;So;0;L;;;;;N;;;;;
+28B4;BRAILLE PATTERN DOTS-3568;So;0;L;;;;;N;;;;;
+28B5;BRAILLE PATTERN DOTS-13568;So;0;L;;;;;N;;;;;
+28B6;BRAILLE PATTERN DOTS-23568;So;0;L;;;;;N;;;;;
+28B7;BRAILLE PATTERN DOTS-123568;So;0;L;;;;;N;;;;;
+28B8;BRAILLE PATTERN DOTS-4568;So;0;L;;;;;N;;;;;
+28B9;BRAILLE PATTERN DOTS-14568;So;0;L;;;;;N;;;;;
+28BA;BRAILLE PATTERN DOTS-24568;So;0;L;;;;;N;;;;;
+28BB;BRAILLE PATTERN DOTS-124568;So;0;L;;;;;N;;;;;
+28BC;BRAILLE PATTERN DOTS-34568;So;0;L;;;;;N;;;;;
+28BD;BRAILLE PATTERN DOTS-134568;So;0;L;;;;;N;;;;;
+28BE;BRAILLE PATTERN DOTS-234568;So;0;L;;;;;N;;;;;
+28BF;BRAILLE PATTERN DOTS-1234568;So;0;L;;;;;N;;;;;
+28C0;BRAILLE PATTERN DOTS-78;So;0;L;;;;;N;;;;;
+28C1;BRAILLE PATTERN DOTS-178;So;0;L;;;;;N;;;;;
+28C2;BRAILLE PATTERN DOTS-278;So;0;L;;;;;N;;;;;
+28C3;BRAILLE PATTERN DOTS-1278;So;0;L;;;;;N;;;;;
+28C4;BRAILLE PATTERN DOTS-378;So;0;L;;;;;N;;;;;
+28C5;BRAILLE PATTERN DOTS-1378;So;0;L;;;;;N;;;;;
+28C6;BRAILLE PATTERN DOTS-2378;So;0;L;;;;;N;;;;;
+28C7;BRAILLE PATTERN DOTS-12378;So;0;L;;;;;N;;;;;
+28C8;BRAILLE PATTERN DOTS-478;So;0;L;;;;;N;;;;;
+28C9;BRAILLE PATTERN DOTS-1478;So;0;L;;;;;N;;;;;
+28CA;BRAILLE PATTERN DOTS-2478;So;0;L;;;;;N;;;;;
+28CB;BRAILLE PATTERN DOTS-12478;So;0;L;;;;;N;;;;;
+28CC;BRAILLE PATTERN DOTS-3478;So;0;L;;;;;N;;;;;
+28CD;BRAILLE PATTERN DOTS-13478;So;0;L;;;;;N;;;;;
+28CE;BRAILLE PATTERN DOTS-23478;So;0;L;;;;;N;;;;;
+28CF;BRAILLE PATTERN DOTS-123478;So;0;L;;;;;N;;;;;
+28D0;BRAILLE PATTERN DOTS-578;So;0;L;;;;;N;;;;;
+28D1;BRAILLE PATTERN DOTS-1578;So;0;L;;;;;N;;;;;
+28D2;BRAILLE PATTERN DOTS-2578;So;0;L;;;;;N;;;;;
+28D3;BRAILLE PATTERN DOTS-12578;So;0;L;;;;;N;;;;;
+28D4;BRAILLE PATTERN DOTS-3578;So;0;L;;;;;N;;;;;
+28D5;BRAILLE PATTERN DOTS-13578;So;0;L;;;;;N;;;;;
+28D6;BRAILLE PATTERN DOTS-23578;So;0;L;;;;;N;;;;;
+28D7;BRAILLE PATTERN DOTS-123578;So;0;L;;;;;N;;;;;
+28D8;BRAILLE PATTERN DOTS-4578;So;0;L;;;;;N;;;;;
+28D9;BRAILLE PATTERN DOTS-14578;So;0;L;;;;;N;;;;;
+28DA;BRAILLE PATTERN DOTS-24578;So;0;L;;;;;N;;;;;
+28DB;BRAILLE PATTERN DOTS-124578;So;0;L;;;;;N;;;;;
+28DC;BRAILLE PATTERN DOTS-34578;So;0;L;;;;;N;;;;;
+28DD;BRAILLE PATTERN DOTS-134578;So;0;L;;;;;N;;;;;
+28DE;BRAILLE PATTERN DOTS-234578;So;0;L;;;;;N;;;;;
+28DF;BRAILLE PATTERN DOTS-1234578;So;0;L;;;;;N;;;;;
+28E0;BRAILLE PATTERN DOTS-678;So;0;L;;;;;N;;;;;
+28E1;BRAILLE PATTERN DOTS-1678;So;0;L;;;;;N;;;;;
+28E2;BRAILLE PATTERN DOTS-2678;So;0;L;;;;;N;;;;;
+28E3;BRAILLE PATTERN DOTS-12678;So;0;L;;;;;N;;;;;
+28E4;BRAILLE PATTERN DOTS-3678;So;0;L;;;;;N;;;;;
+28E5;BRAILLE PATTERN DOTS-13678;So;0;L;;;;;N;;;;;
+28E6;BRAILLE PATTERN DOTS-23678;So;0;L;;;;;N;;;;;
+28E7;BRAILLE PATTERN DOTS-123678;So;0;L;;;;;N;;;;;
+28E8;BRAILLE PATTERN DOTS-4678;So;0;L;;;;;N;;;;;
+28E9;BRAILLE PATTERN DOTS-14678;So;0;L;;;;;N;;;;;
+28EA;BRAILLE PATTERN DOTS-24678;So;0;L;;;;;N;;;;;
+28EB;BRAILLE PATTERN DOTS-124678;So;0;L;;;;;N;;;;;
+28EC;BRAILLE PATTERN DOTS-34678;So;0;L;;;;;N;;;;;
+28ED;BRAILLE PATTERN DOTS-134678;So;0;L;;;;;N;;;;;
+28EE;BRAILLE PATTERN DOTS-234678;So;0;L;;;;;N;;;;;
+28EF;BRAILLE PATTERN DOTS-1234678;So;0;L;;;;;N;;;;;
+28F0;BRAILLE PATTERN DOTS-5678;So;0;L;;;;;N;;;;;
+28F1;BRAILLE PATTERN DOTS-15678;So;0;L;;;;;N;;;;;
+28F2;BRAILLE PATTERN DOTS-25678;So;0;L;;;;;N;;;;;
+28F3;BRAILLE PATTERN DOTS-125678;So;0;L;;;;;N;;;;;
+28F4;BRAILLE PATTERN DOTS-35678;So;0;L;;;;;N;;;;;
+28F5;BRAILLE PATTERN DOTS-135678;So;0;L;;;;;N;;;;;
+28F6;BRAILLE PATTERN DOTS-235678;So;0;L;;;;;N;;;;;
+28F7;BRAILLE PATTERN DOTS-1235678;So;0;L;;;;;N;;;;;
+28F8;BRAILLE PATTERN DOTS-45678;So;0;L;;;;;N;;;;;
+28F9;BRAILLE PATTERN DOTS-145678;So;0;L;;;;;N;;;;;
+28FA;BRAILLE PATTERN DOTS-245678;So;0;L;;;;;N;;;;;
+28FB;BRAILLE PATTERN DOTS-1245678;So;0;L;;;;;N;;;;;
+28FC;BRAILLE PATTERN DOTS-345678;So;0;L;;;;;N;;;;;
+28FD;BRAILLE PATTERN DOTS-1345678;So;0;L;;;;;N;;;;;
+28FE;BRAILLE PATTERN DOTS-2345678;So;0;L;;;;;N;;;;;
+28FF;BRAILLE PATTERN DOTS-12345678;So;0;L;;;;;N;;;;;
+2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
+2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
+290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;;
+290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;;
+290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
+290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
+290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
+290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
+2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
+2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;;
+2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;;
+2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;;
+2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;;
+2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
+291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
+291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
+291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;;
+291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
+291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
+291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
+2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
+2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
+2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
+2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
+2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
+2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;;
+2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
+292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
+292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;;
+292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;;
+292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;;
+2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;;
+2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;;
+2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;;
+2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;;
+2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;;
+2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;;
+2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
+2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
+293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
+293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
+293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;;
+293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;;
+293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
+293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;;
+2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
+2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;;
+2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;;
+2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;;
+2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;;
+2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
+2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
+294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;;
+294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;;
+294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;;
+294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;;
+294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;;
+294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;;
+2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;;
+2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;;
+2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;;
+2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;;
+2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;;
+2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;;
+2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;;
+2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;;
+2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;;
+2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;;
+295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;;
+295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;;
+295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;;
+295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;;
+295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;;
+295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;;
+2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;;
+2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;;
+2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
+2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
+2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
+2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
+2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;;
+2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
+2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;;
+2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;;
+296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;;
+296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;;
+296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;;
+296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;;
+296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
+296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;;
+2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;;
+2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
+2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
+2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
+2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;;
+2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;;
+297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;;
+297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;;
+297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;;
+297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;;
+2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;;
+2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;;
+2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;;
+2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;;
+2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;;
+2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
+2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
+2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;;
+2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;;
+2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;;
+298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;;
+298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;;
+298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;;
+298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;;
+298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;;
+298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;;
+2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;;
+2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;;
+2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;;
+2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;;
+2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;;
+2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;;
+2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;;
+2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;;
+2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;;
+2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;;
+299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;;
+299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;;
+299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;;
+299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;;
+299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;;
+299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;;
+29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;;
+29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;;
+29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;;
+29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;;
+29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
+29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
+29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;;
+29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;;
+29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;;
+29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;;
+29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;;
+29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;;
+29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;;
+29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;;
+29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;;
+29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;;
+29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;;
+29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
+29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
+29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;;
+29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;;
+29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;;
+29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
+29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;;
+29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;;
+29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;;
+29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
+29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;;
+29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;;
+29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;;
+29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;;
+29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;;
+29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;;
+29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;;
+29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;;
+29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;;
+29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;;
+29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
+29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;;
+29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;;
+29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
+29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
+29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
+29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;;
+29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;;
+29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;;
+29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;;
+29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
+29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
+29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;;
+29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
+29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
+29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;;
+29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;;
+29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;;
+29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;;
+29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;;
+29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;;
+29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;;
+29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;;
+29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
+29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;;
+29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;;
+29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;;
+29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;;
+29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;;
+29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;;
+29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;;
+29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;;
+29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;;
+29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
+29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;;
+29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;;
+29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;;
+29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;;
+29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;;
+29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;;
+29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;;
+29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;;
+29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;;
+29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;;
+29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;;
+29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;;
+29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;;
+29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
+29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;;
+29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;;
+29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;;
+29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;;
+29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;;
+29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;;
+29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;;
+29FE;TINY;Sm;0;ON;;;;;N;;;;;
+29FF;MINY;Sm;0;ON;;;;;N;;;;;
+2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;;
+2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;;
+2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;;
+2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;;
+2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON;<compat> 222B 222B 222B 222B;;;;Y;;;;;
+2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;;
+2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;;
+2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;;
+2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;;
+2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;;
+2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;;
+2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;;
+2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;;
+2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;;
+2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;;
+2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;;
+2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;;
+2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;;
+2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
+2A1D;JOIN;Sm;0;ON;;;;;N;;;;;
+2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;;
+2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;;
+2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;;
+2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
+2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;;
+2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;;
+2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;;
+2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;;
+2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;;
+2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;;
+2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;;
+2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;;
+2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
+2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
+2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;;
+2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
+2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
+2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;;
+2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;;
+2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
+2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;;
+2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;;
+2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;;
+2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;;
+2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
+2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
+2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;;
+2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;;
+2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;;
+2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;;
+2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;;
+2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;;
+2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;;
+2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
+2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
+2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;;
+2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;;
+2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;;
+2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;;
+2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;;
+2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;;
+2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;;
+2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;;
+2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;;
+2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;;
+2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;;
+2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;;
+2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;;
+2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
+2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
+2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;;
+2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;;
+2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;;
+2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;;
+2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;;
+2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;;
+2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;;
+2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;;
+2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;;
+2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;;
+2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;;
+2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;;
+2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
+2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;;
+2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
+2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;;
+2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;;
+2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;;
+2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;;
+2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;;
+2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;;
+2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;;
+2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;;
+2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;;
+2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;;
+2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;;
+2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;;
+2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2A74;DOUBLE COLON EQUAL;Sm;0;ON;<compat> 003A 003A 003D;;;;Y;;;;;
+2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D;;;;N;;;;;
+2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D 003D;;;;N;;;;;
+2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;;
+2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;;
+2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;;
+2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;;
+2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
+2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
+2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
+2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;;
+2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;;
+2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
+2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
+2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
+2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;;
+2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;;
+2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;;
+2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;;
+2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;;
+2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
+2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
+2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
+2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;;
+2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;;
+2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;;
+2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;;
+2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;;
+2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;;
+2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
+2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;;
+2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;;
+2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;;
+2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;;
+2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;;
+2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;;
+2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;;
+2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;;
+2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
+2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
+2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
+2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;;
+2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
+2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;;
+2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;;
+2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;;
+2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;;
+2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;;
+2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;;
+2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;;
+2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;;
+2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;;
+2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;;
+2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;;
+2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;;
+2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;;
+2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;;;;
+2ADD;NONFORKING;Sm;0;ON;;;;;N;;;;;
+2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;;
+2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;;
+2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;;
+2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;;
+2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
+2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
+2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
+2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;;
+2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;;
+2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;;
+2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;;
+2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;;
+2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;;
+2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;;
+2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;;
+2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;;
+2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;;
+2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;;
+2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;;
+2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;;
+2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
+2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;;
+2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;;
+2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;;
+2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;;
+2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;;
+2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;;
+2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;;
+2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;;
+2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;;
+2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
+2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;;
+2B00;NORTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;;
+2B01;NORTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;;
+2B02;SOUTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;;
+2B03;SOUTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;;
+2B04;LEFT RIGHT WHITE ARROW;So;0;ON;;;;;N;;;;;
+2B05;LEFTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B06;UPWARDS BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B07;DOWNWARDS BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B08;NORTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B09;NORTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B0A;SOUTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B0B;SOUTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B0C;LEFT RIGHT BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B0D;UP DOWN BLACK ARROW;So;0;ON;;;;;N;;;;;
+2B0E;RIGHTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;;
+2B0F;RIGHTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;;
+2B10;LEFTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;;
+2B11;LEFTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;;
+2B12;SQUARE WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;;
+2B13;SQUARE WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;;
+2B14;SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
+2B15;SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;;
+2B16;DIAMOND WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;;
+2B17;DIAMOND WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;;
+2B18;DIAMOND WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;;
+2B19;DIAMOND WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;;
+2B1A;DOTTED SQUARE;So;0;ON;;;;;N;;;;;
+2B1B;BLACK LARGE SQUARE;So;0;ON;;;;;N;;;;;
+2B1C;WHITE LARGE SQUARE;So;0;ON;;;;;N;;;;;
+2B1D;BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;;
+2B1E;WHITE VERY SMALL SQUARE;So;0;ON;;;;;N;;;;;
+2B1F;BLACK PENTAGON;So;0;ON;;;;;N;;;;;
+2B20;WHITE PENTAGON;So;0;ON;;;;;N;;;;;
+2B21;WHITE HEXAGON;So;0;ON;;;;;N;;;;;
+2B22;BLACK HEXAGON;So;0;ON;;;;;N;;;;;
+2B23;HORIZONTAL BLACK HEXAGON;So;0;ON;;;;;N;;;;;
+2B24;BLACK LARGE CIRCLE;So;0;ON;;;;;N;;;;;
+2B25;BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;;
+2B26;WHITE MEDIUM DIAMOND;So;0;ON;;;;;N;;;;;
+2B27;BLACK MEDIUM LOZENGE;So;0;ON;;;;;N;;;;;
+2B28;WHITE MEDIUM LOZENGE;So;0;ON;;;;;N;;;;;
+2B29;BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;;
+2B2A;BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;;
+2B2B;WHITE SMALL LOZENGE;So;0;ON;;;;;N;;;;;
+2B2C;BLACK HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;;
+2B2D;WHITE HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;;
+2B2E;BLACK VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;;
+2B2F;WHITE VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;;
+2B30;LEFT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;;
+2B31;THREE LEFTWARDS ARROWS;Sm;0;ON;;;;;N;;;;;
+2B32;LEFT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;;
+2B33;LONG LEFTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;;
+2B34;LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2B35;LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2B36;LEFTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;;
+2B37;LEFTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;;
+2B38;LEFTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;;
+2B39;LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2B3A;LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2B3B;LEFTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;;
+2B3C;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2B3D;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;;
+2B3E;LEFTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;;
+2B3F;WAVE ARROW POINTING DIRECTLY LEFT;Sm;0;ON;;;;;N;;;;;
+2B40;EQUALS SIGN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2B41;REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2B42;LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
+2B43;RIGHTWARDS ARROW THROUGH GREATER-THAN;Sm;0;ON;;;;;N;;;;;
+2B44;RIGHTWARDS ARROW THROUGH SUPERSET;Sm;0;ON;;;;;N;;;;;
+2B45;LEFTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;;
+2B46;RIGHTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;;
+2B47;REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2B48;RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
+2B49;TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
+2B4A;LEFTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;;
+2B4B;LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
+2B4C;RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;;
+2B50;WHITE MEDIUM STAR;So;0;ON;;;;;N;;;;;
+2B51;BLACK SMALL STAR;So;0;ON;;;;;N;;;;;
+2B52;WHITE SMALL STAR;So;0;ON;;;;;N;;;;;
+2B53;BLACK RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;;
+2B54;WHITE RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;;
+2B55;HEAVY LARGE CIRCLE;So;0;ON;;;;;N;;;;;
+2B56;HEAVY OVAL WITH OVAL INSIDE;So;0;ON;;;;;N;;;;;
+2B57;HEAVY CIRCLE WITH CIRCLE INSIDE;So;0;ON;;;;;N;;;;;
+2B58;HEAVY CIRCLE;So;0;ON;;;;;N;;;;;
+2B59;HEAVY CIRCLED SALTIRE;So;0;ON;;;;;N;;;;;
+2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30;
+2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31;
+2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32;
+2C03;GLAGOLITIC CAPITAL LETTER GLAGOLI;Lu;0;L;;;;;N;;;;2C33;
+2C04;GLAGOLITIC CAPITAL LETTER DOBRO;Lu;0;L;;;;;N;;;;2C34;
+2C05;GLAGOLITIC CAPITAL LETTER YESTU;Lu;0;L;;;;;N;;;;2C35;
+2C06;GLAGOLITIC CAPITAL LETTER ZHIVETE;Lu;0;L;;;;;N;;;;2C36;
+2C07;GLAGOLITIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;2C37;
+2C08;GLAGOLITIC CAPITAL LETTER ZEMLJA;Lu;0;L;;;;;N;;;;2C38;
+2C09;GLAGOLITIC CAPITAL LETTER IZHE;Lu;0;L;;;;;N;;;;2C39;
+2C0A;GLAGOLITIC CAPITAL LETTER INITIAL IZHE;Lu;0;L;;;;;N;;;;2C3A;
+2C0B;GLAGOLITIC CAPITAL LETTER I;Lu;0;L;;;;;N;;;;2C3B;
+2C0C;GLAGOLITIC CAPITAL LETTER DJERVI;Lu;0;L;;;;;N;;;;2C3C;
+2C0D;GLAGOLITIC CAPITAL LETTER KAKO;Lu;0;L;;;;;N;;;;2C3D;
+2C0E;GLAGOLITIC CAPITAL LETTER LJUDIJE;Lu;0;L;;;;;N;;;;2C3E;
+2C0F;GLAGOLITIC CAPITAL LETTER MYSLITE;Lu;0;L;;;;;N;;;;2C3F;
+2C10;GLAGOLITIC CAPITAL LETTER NASHI;Lu;0;L;;;;;N;;;;2C40;
+2C11;GLAGOLITIC CAPITAL LETTER ONU;Lu;0;L;;;;;N;;;;2C41;
+2C12;GLAGOLITIC CAPITAL LETTER POKOJI;Lu;0;L;;;;;N;;;;2C42;
+2C13;GLAGOLITIC CAPITAL LETTER RITSI;Lu;0;L;;;;;N;;;;2C43;
+2C14;GLAGOLITIC CAPITAL LETTER SLOVO;Lu;0;L;;;;;N;;;;2C44;
+2C15;GLAGOLITIC CAPITAL LETTER TVRIDO;Lu;0;L;;;;;N;;;;2C45;
+2C16;GLAGOLITIC CAPITAL LETTER UKU;Lu;0;L;;;;;N;;;;2C46;
+2C17;GLAGOLITIC CAPITAL LETTER FRITU;Lu;0;L;;;;;N;;;;2C47;
+2C18;GLAGOLITIC CAPITAL LETTER HERU;Lu;0;L;;;;;N;;;;2C48;
+2C19;GLAGOLITIC CAPITAL LETTER OTU;Lu;0;L;;;;;N;;;;2C49;
+2C1A;GLAGOLITIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;2C4A;
+2C1B;GLAGOLITIC CAPITAL LETTER SHTA;Lu;0;L;;;;;N;;;;2C4B;
+2C1C;GLAGOLITIC CAPITAL LETTER TSI;Lu;0;L;;;;;N;;;;2C4C;
+2C1D;GLAGOLITIC CAPITAL LETTER CHRIVI;Lu;0;L;;;;;N;;;;2C4D;
+2C1E;GLAGOLITIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;2C4E;
+2C1F;GLAGOLITIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;;;;2C4F;
+2C20;GLAGOLITIC CAPITAL LETTER YERI;Lu;0;L;;;;;N;;;;2C50;
+2C21;GLAGOLITIC CAPITAL LETTER YATI;Lu;0;L;;;;;N;;;;2C51;
+2C22;GLAGOLITIC CAPITAL LETTER SPIDERY HA;Lu;0;L;;;;;N;;;;2C52;
+2C23;GLAGOLITIC CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;2C53;
+2C24;GLAGOLITIC CAPITAL LETTER SMALL YUS;Lu;0;L;;;;;N;;;;2C54;
+2C25;GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL;Lu;0;L;;;;;N;;;;2C55;
+2C26;GLAGOLITIC CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;2C56;
+2C27;GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS;Lu;0;L;;;;;N;;;;2C57;
+2C28;GLAGOLITIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;2C58;
+2C29;GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS;Lu;0;L;;;;;N;;;;2C59;
+2C2A;GLAGOLITIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;2C5A;
+2C2B;GLAGOLITIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;2C5B;
+2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C;
+2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D;
+2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E;
+2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00
+2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01
+2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02
+2C33;GLAGOLITIC SMALL LETTER GLAGOLI;Ll;0;L;;;;;N;;;2C03;;2C03
+2C34;GLAGOLITIC SMALL LETTER DOBRO;Ll;0;L;;;;;N;;;2C04;;2C04
+2C35;GLAGOLITIC SMALL LETTER YESTU;Ll;0;L;;;;;N;;;2C05;;2C05
+2C36;GLAGOLITIC SMALL LETTER ZHIVETE;Ll;0;L;;;;;N;;;2C06;;2C06
+2C37;GLAGOLITIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;2C07;;2C07
+2C38;GLAGOLITIC SMALL LETTER ZEMLJA;Ll;0;L;;;;;N;;;2C08;;2C08
+2C39;GLAGOLITIC SMALL LETTER IZHE;Ll;0;L;;;;;N;;;2C09;;2C09
+2C3A;GLAGOLITIC SMALL LETTER INITIAL IZHE;Ll;0;L;;;;;N;;;2C0A;;2C0A
+2C3B;GLAGOLITIC SMALL LETTER I;Ll;0;L;;;;;N;;;2C0B;;2C0B
+2C3C;GLAGOLITIC SMALL LETTER DJERVI;Ll;0;L;;;;;N;;;2C0C;;2C0C
+2C3D;GLAGOLITIC SMALL LETTER KAKO;Ll;0;L;;;;;N;;;2C0D;;2C0D
+2C3E;GLAGOLITIC SMALL LETTER LJUDIJE;Ll;0;L;;;;;N;;;2C0E;;2C0E
+2C3F;GLAGOLITIC SMALL LETTER MYSLITE;Ll;0;L;;;;;N;;;2C0F;;2C0F
+2C40;GLAGOLITIC SMALL LETTER NASHI;Ll;0;L;;;;;N;;;2C10;;2C10
+2C41;GLAGOLITIC SMALL LETTER ONU;Ll;0;L;;;;;N;;;2C11;;2C11
+2C42;GLAGOLITIC SMALL LETTER POKOJI;Ll;0;L;;;;;N;;;2C12;;2C12
+2C43;GLAGOLITIC SMALL LETTER RITSI;Ll;0;L;;;;;N;;;2C13;;2C13
+2C44;GLAGOLITIC SMALL LETTER SLOVO;Ll;0;L;;;;;N;;;2C14;;2C14
+2C45;GLAGOLITIC SMALL LETTER TVRIDO;Ll;0;L;;;;;N;;;2C15;;2C15
+2C46;GLAGOLITIC SMALL LETTER UKU;Ll;0;L;;;;;N;;;2C16;;2C16
+2C47;GLAGOLITIC SMALL LETTER FRITU;Ll;0;L;;;;;N;;;2C17;;2C17
+2C48;GLAGOLITIC SMALL LETTER HERU;Ll;0;L;;;;;N;;;2C18;;2C18
+2C49;GLAGOLITIC SMALL LETTER OTU;Ll;0;L;;;;;N;;;2C19;;2C19
+2C4A;GLAGOLITIC SMALL LETTER PE;Ll;0;L;;;;;N;;;2C1A;;2C1A
+2C4B;GLAGOLITIC SMALL LETTER SHTA;Ll;0;L;;;;;N;;;2C1B;;2C1B
+2C4C;GLAGOLITIC SMALL LETTER TSI;Ll;0;L;;;;;N;;;2C1C;;2C1C
+2C4D;GLAGOLITIC SMALL LETTER CHRIVI;Ll;0;L;;;;;N;;;2C1D;;2C1D
+2C4E;GLAGOLITIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;2C1E;;2C1E
+2C4F;GLAGOLITIC SMALL LETTER YERU;Ll;0;L;;;;;N;;;2C1F;;2C1F
+2C50;GLAGOLITIC SMALL LETTER YERI;Ll;0;L;;;;;N;;;2C20;;2C20
+2C51;GLAGOLITIC SMALL LETTER YATI;Ll;0;L;;;;;N;;;2C21;;2C21
+2C52;GLAGOLITIC SMALL LETTER SPIDERY HA;Ll;0;L;;;;;N;;;2C22;;2C22
+2C53;GLAGOLITIC SMALL LETTER YU;Ll;0;L;;;;;N;;;2C23;;2C23
+2C54;GLAGOLITIC SMALL LETTER SMALL YUS;Ll;0;L;;;;;N;;;2C24;;2C24
+2C55;GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL;Ll;0;L;;;;;N;;;2C25;;2C25
+2C56;GLAGOLITIC SMALL LETTER YO;Ll;0;L;;;;;N;;;2C26;;2C26
+2C57;GLAGOLITIC SMALL LETTER IOTATED SMALL YUS;Ll;0;L;;;;;N;;;2C27;;2C27
+2C58;GLAGOLITIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;2C28;;2C28
+2C59;GLAGOLITIC SMALL LETTER IOTATED BIG YUS;Ll;0;L;;;;;N;;;2C29;;2C29
+2C5A;GLAGOLITIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;2C2A;;2C2A
+2C5B;GLAGOLITIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;2C2B;;2C2B
+2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C
+2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D
+2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E
+2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61;
+2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60
+2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B;
+2C63;LATIN CAPITAL LETTER P WITH STROKE;Lu;0;L;;;;;N;;;;1D7D;
+2C64;LATIN CAPITAL LETTER R WITH TAIL;Lu;0;L;;;;;N;;;;027D;
+2C65;LATIN SMALL LETTER A WITH STROKE;Ll;0;L;;;;;N;;;023A;;023A
+2C66;LATIN SMALL LETTER T WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;023E;;023E
+2C67;LATIN CAPITAL LETTER H WITH DESCENDER;Lu;0;L;;;;;N;;;;2C68;
+2C68;LATIN SMALL LETTER H WITH DESCENDER;Ll;0;L;;;;;N;;;2C67;;2C67
+2C69;LATIN CAPITAL LETTER K WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6A;
+2C6A;LATIN SMALL LETTER K WITH DESCENDER;Ll;0;L;;;;;N;;;2C69;;2C69
+2C6B;LATIN CAPITAL LETTER Z WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6C;
+2C6C;LATIN SMALL LETTER Z WITH DESCENDER;Ll;0;L;;;;;N;;;2C6B;;2C6B
+2C6D;LATIN CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;0251;
+2C6E;LATIN CAPITAL LETTER M WITH HOOK;Lu;0;L;;;;;N;;;;0271;
+2C6F;LATIN CAPITAL LETTER TURNED A;Lu;0;L;;;;;N;;;;0250;
+2C70;LATIN CAPITAL LETTER TURNED ALPHA;Lu;0;L;;;;;N;;;;0252;
+2C71;LATIN SMALL LETTER V WITH RIGHT HOOK;Ll;0;L;;;;;N;;;;;
+2C72;LATIN CAPITAL LETTER W WITH HOOK;Lu;0;L;;;;;N;;;;2C73;
+2C73;LATIN SMALL LETTER W WITH HOOK;Ll;0;L;;;;;N;;;2C72;;2C72
+2C74;LATIN SMALL LETTER V WITH CURL;Ll;0;L;;;;;N;;;;;
+2C75;LATIN CAPITAL LETTER HALF H;Lu;0;L;;;;;N;;;;2C76;
+2C76;LATIN SMALL LETTER HALF H;Ll;0;L;;;;;N;;;2C75;;2C75
+2C77;LATIN SMALL LETTER TAILLESS PHI;Ll;0;L;;;;;N;;;;;
+2C78;LATIN SMALL LETTER E WITH NOTCH;Ll;0;L;;;;;N;;;;;
+2C79;LATIN SMALL LETTER TURNED R WITH TAIL;Ll;0;L;;;;;N;;;;;
+2C7A;LATIN SMALL LETTER O WITH LOW RING INSIDE;Ll;0;L;;;;;N;;;;;
+2C7B;LATIN LETTER SMALL CAPITAL TURNED E;Ll;0;L;;;;;N;;;;;
+2C7C;LATIN SUBSCRIPT SMALL LETTER J;Ll;0;L;<sub> 006A;;;;N;;;;;
+2C7D;MODIFIER LETTER CAPITAL V;Lm;0;L;<super> 0056;;;;N;;;;;
+2C7E;LATIN CAPITAL LETTER S WITH SWASH TAIL;Lu;0;L;;;;;N;;;;023F;
+2C7F;LATIN CAPITAL LETTER Z WITH SWASH TAIL;Lu;0;L;;;;;N;;;;0240;
+2C80;COPTIC CAPITAL LETTER ALFA;Lu;0;L;;;;;N;;;;2C81;
+2C81;COPTIC SMALL LETTER ALFA;Ll;0;L;;;;;N;;;2C80;;2C80
+2C82;COPTIC CAPITAL LETTER VIDA;Lu;0;L;;;;;N;;;;2C83;
+2C83;COPTIC SMALL LETTER VIDA;Ll;0;L;;;;;N;;;2C82;;2C82
+2C84;COPTIC CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;2C85;
+2C85;COPTIC SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;2C84;;2C84
+2C86;COPTIC CAPITAL LETTER DALDA;Lu;0;L;;;;;N;;;;2C87;
+2C87;COPTIC SMALL LETTER DALDA;Ll;0;L;;;;;N;;;2C86;;2C86
+2C88;COPTIC CAPITAL LETTER EIE;Lu;0;L;;;;;N;;;;2C89;
+2C89;COPTIC SMALL LETTER EIE;Ll;0;L;;;;;N;;;2C88;;2C88
+2C8A;COPTIC CAPITAL LETTER SOU;Lu;0;L;;;;;N;;;;2C8B;
+2C8B;COPTIC SMALL LETTER SOU;Ll;0;L;;;;;N;;;2C8A;;2C8A
+2C8C;COPTIC CAPITAL LETTER ZATA;Lu;0;L;;;;;N;;;;2C8D;
+2C8D;COPTIC SMALL LETTER ZATA;Ll;0;L;;;;;N;;;2C8C;;2C8C
+2C8E;COPTIC CAPITAL LETTER HATE;Lu;0;L;;;;;N;;;;2C8F;
+2C8F;COPTIC SMALL LETTER HATE;Ll;0;L;;;;;N;;;2C8E;;2C8E
+2C90;COPTIC CAPITAL LETTER THETHE;Lu;0;L;;;;;N;;;;2C91;
+2C91;COPTIC SMALL LETTER THETHE;Ll;0;L;;;;;N;;;2C90;;2C90
+2C92;COPTIC CAPITAL LETTER IAUDA;Lu;0;L;;;;;N;;;;2C93;
+2C93;COPTIC SMALL LETTER IAUDA;Ll;0;L;;;;;N;;;2C92;;2C92
+2C94;COPTIC CAPITAL LETTER KAPA;Lu;0;L;;;;;N;;;;2C95;
+2C95;COPTIC SMALL LETTER KAPA;Ll;0;L;;;;;N;;;2C94;;2C94
+2C96;COPTIC CAPITAL LETTER LAULA;Lu;0;L;;;;;N;;;;2C97;
+2C97;COPTIC SMALL LETTER LAULA;Ll;0;L;;;;;N;;;2C96;;2C96
+2C98;COPTIC CAPITAL LETTER MI;Lu;0;L;;;;;N;;;;2C99;
+2C99;COPTIC SMALL LETTER MI;Ll;0;L;;;;;N;;;2C98;;2C98
+2C9A;COPTIC CAPITAL LETTER NI;Lu;0;L;;;;;N;;;;2C9B;
+2C9B;COPTIC SMALL LETTER NI;Ll;0;L;;;;;N;;;2C9A;;2C9A
+2C9C;COPTIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;2C9D;
+2C9D;COPTIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;2C9C;;2C9C
+2C9E;COPTIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;2C9F;
+2C9F;COPTIC SMALL LETTER O;Ll;0;L;;;;;N;;;2C9E;;2C9E
+2CA0;COPTIC CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;2CA1;
+2CA1;COPTIC SMALL LETTER PI;Ll;0;L;;;;;N;;;2CA0;;2CA0
+2CA2;COPTIC CAPITAL LETTER RO;Lu;0;L;;;;;N;;;;2CA3;
+2CA3;COPTIC SMALL LETTER RO;Ll;0;L;;;;;N;;;2CA2;;2CA2
+2CA4;COPTIC CAPITAL LETTER SIMA;Lu;0;L;;;;;N;;;;2CA5;
+2CA5;COPTIC SMALL LETTER SIMA;Ll;0;L;;;;;N;;;2CA4;;2CA4
+2CA6;COPTIC CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;2CA7;
+2CA7;COPTIC SMALL LETTER TAU;Ll;0;L;;;;;N;;;2CA6;;2CA6
+2CA8;COPTIC CAPITAL LETTER UA;Lu;0;L;;;;;N;;;;2CA9;
+2CA9;COPTIC SMALL LETTER UA;Ll;0;L;;;;;N;;;2CA8;;2CA8
+2CAA;COPTIC CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;2CAB;
+2CAB;COPTIC SMALL LETTER FI;Ll;0;L;;;;;N;;;2CAA;;2CAA
+2CAC;COPTIC CAPITAL LETTER KHI;Lu;0;L;;;;;N;;;;2CAD;
+2CAD;COPTIC SMALL LETTER KHI;Ll;0;L;;;;;N;;;2CAC;;2CAC
+2CAE;COPTIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;2CAF;
+2CAF;COPTIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;2CAE;;2CAE
+2CB0;COPTIC CAPITAL LETTER OOU;Lu;0;L;;;;;N;;;;2CB1;
+2CB1;COPTIC SMALL LETTER OOU;Ll;0;L;;;;;N;;;2CB0;;2CB0
+2CB2;COPTIC CAPITAL LETTER DIALECT-P ALEF;Lu;0;L;;;;;N;;;;2CB3;
+2CB3;COPTIC SMALL LETTER DIALECT-P ALEF;Ll;0;L;;;;;N;;;2CB2;;2CB2
+2CB4;COPTIC CAPITAL LETTER OLD COPTIC AIN;Lu;0;L;;;;;N;;;;2CB5;
+2CB5;COPTIC SMALL LETTER OLD COPTIC AIN;Ll;0;L;;;;;N;;;2CB4;;2CB4
+2CB6;COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE;Lu;0;L;;;;;N;;;;2CB7;
+2CB7;COPTIC SMALL LETTER CRYPTOGRAMMIC EIE;Ll;0;L;;;;;N;;;2CB6;;2CB6
+2CB8;COPTIC CAPITAL LETTER DIALECT-P KAPA;Lu;0;L;;;;;N;;;;2CB9;
+2CB9;COPTIC SMALL LETTER DIALECT-P KAPA;Ll;0;L;;;;;N;;;2CB8;;2CB8
+2CBA;COPTIC CAPITAL LETTER DIALECT-P NI;Lu;0;L;;;;;N;;;;2CBB;
+2CBB;COPTIC SMALL LETTER DIALECT-P NI;Ll;0;L;;;;;N;;;2CBA;;2CBA
+2CBC;COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI;Lu;0;L;;;;;N;;;;2CBD;
+2CBD;COPTIC SMALL LETTER CRYPTOGRAMMIC NI;Ll;0;L;;;;;N;;;2CBC;;2CBC
+2CBE;COPTIC CAPITAL LETTER OLD COPTIC OOU;Lu;0;L;;;;;N;;;;2CBF;
+2CBF;COPTIC SMALL LETTER OLD COPTIC OOU;Ll;0;L;;;;;N;;;2CBE;;2CBE
+2CC0;COPTIC CAPITAL LETTER SAMPI;Lu;0;L;;;;;N;;;;2CC1;
+2CC1;COPTIC SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;2CC0;;2CC0
+2CC2;COPTIC CAPITAL LETTER CROSSED SHEI;Lu;0;L;;;;;N;;;;2CC3;
+2CC3;COPTIC SMALL LETTER CROSSED SHEI;Ll;0;L;;;;;N;;;2CC2;;2CC2
+2CC4;COPTIC CAPITAL LETTER OLD COPTIC SHEI;Lu;0;L;;;;;N;;;;2CC5;
+2CC5;COPTIC SMALL LETTER OLD COPTIC SHEI;Ll;0;L;;;;;N;;;2CC4;;2CC4
+2CC6;COPTIC CAPITAL LETTER OLD COPTIC ESH;Lu;0;L;;;;;N;;;;2CC7;
+2CC7;COPTIC SMALL LETTER OLD COPTIC ESH;Ll;0;L;;;;;N;;;2CC6;;2CC6
+2CC8;COPTIC CAPITAL LETTER AKHMIMIC KHEI;Lu;0;L;;;;;N;;;;2CC9;
+2CC9;COPTIC SMALL LETTER AKHMIMIC KHEI;Ll;0;L;;;;;N;;;2CC8;;2CC8
+2CCA;COPTIC CAPITAL LETTER DIALECT-P HORI;Lu;0;L;;;;;N;;;;2CCB;
+2CCB;COPTIC SMALL LETTER DIALECT-P HORI;Ll;0;L;;;;;N;;;2CCA;;2CCA
+2CCC;COPTIC CAPITAL LETTER OLD COPTIC HORI;Lu;0;L;;;;;N;;;;2CCD;
+2CCD;COPTIC SMALL LETTER OLD COPTIC HORI;Ll;0;L;;;;;N;;;2CCC;;2CCC
+2CCE;COPTIC CAPITAL LETTER OLD COPTIC HA;Lu;0;L;;;;;N;;;;2CCF;
+2CCF;COPTIC SMALL LETTER OLD COPTIC HA;Ll;0;L;;;;;N;;;2CCE;;2CCE
+2CD0;COPTIC CAPITAL LETTER L-SHAPED HA;Lu;0;L;;;;;N;;;;2CD1;
+2CD1;COPTIC SMALL LETTER L-SHAPED HA;Ll;0;L;;;;;N;;;2CD0;;2CD0
+2CD2;COPTIC CAPITAL LETTER OLD COPTIC HEI;Lu;0;L;;;;;N;;;;2CD3;
+2CD3;COPTIC SMALL LETTER OLD COPTIC HEI;Ll;0;L;;;;;N;;;2CD2;;2CD2
+2CD4;COPTIC CAPITAL LETTER OLD COPTIC HAT;Lu;0;L;;;;;N;;;;2CD5;
+2CD5;COPTIC SMALL LETTER OLD COPTIC HAT;Ll;0;L;;;;;N;;;2CD4;;2CD4
+2CD6;COPTIC CAPITAL LETTER OLD COPTIC GANGIA;Lu;0;L;;;;;N;;;;2CD7;
+2CD7;COPTIC SMALL LETTER OLD COPTIC GANGIA;Ll;0;L;;;;;N;;;2CD6;;2CD6
+2CD8;COPTIC CAPITAL LETTER OLD COPTIC DJA;Lu;0;L;;;;;N;;;;2CD9;
+2CD9;COPTIC SMALL LETTER OLD COPTIC DJA;Ll;0;L;;;;;N;;;2CD8;;2CD8
+2CDA;COPTIC CAPITAL LETTER OLD COPTIC SHIMA;Lu;0;L;;;;;N;;;;2CDB;
+2CDB;COPTIC SMALL LETTER OLD COPTIC SHIMA;Ll;0;L;;;;;N;;;2CDA;;2CDA
+2CDC;COPTIC CAPITAL LETTER OLD NUBIAN SHIMA;Lu;0;L;;;;;N;;;;2CDD;
+2CDD;COPTIC SMALL LETTER OLD NUBIAN SHIMA;Ll;0;L;;;;;N;;;2CDC;;2CDC
+2CDE;COPTIC CAPITAL LETTER OLD NUBIAN NGI;Lu;0;L;;;;;N;;;;2CDF;
+2CDF;COPTIC SMALL LETTER OLD NUBIAN NGI;Ll;0;L;;;;;N;;;2CDE;;2CDE
+2CE0;COPTIC CAPITAL LETTER OLD NUBIAN NYI;Lu;0;L;;;;;N;;;;2CE1;
+2CE1;COPTIC SMALL LETTER OLD NUBIAN NYI;Ll;0;L;;;;;N;;;2CE0;;2CE0
+2CE2;COPTIC CAPITAL LETTER OLD NUBIAN WAU;Lu;0;L;;;;;N;;;;2CE3;
+2CE3;COPTIC SMALL LETTER OLD NUBIAN WAU;Ll;0;L;;;;;N;;;2CE2;;2CE2
+2CE4;COPTIC SYMBOL KAI;Ll;0;L;;;;;N;;;;;
+2CE5;COPTIC SYMBOL MI RO;So;0;ON;;;;;N;;;;;
+2CE6;COPTIC SYMBOL PI RO;So;0;ON;;;;;N;;;;;
+2CE7;COPTIC SYMBOL STAUROS;So;0;ON;;;;;N;;;;;
+2CE8;COPTIC SYMBOL TAU RO;So;0;ON;;;;;N;;;;;
+2CE9;COPTIC SYMBOL KHI RO;So;0;ON;;;;;N;;;;;
+2CEA;COPTIC SYMBOL SHIMA SIMA;So;0;ON;;;;;N;;;;;
+2CEB;COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI;Lu;0;L;;;;;N;;;;2CEC;
+2CEC;COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI;Ll;0;L;;;;;N;;;2CEB;;2CEB
+2CED;COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA;Lu;0;L;;;;;N;;;;2CEE;
+2CEE;COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA;Ll;0;L;;;;;N;;;2CED;;2CED
+2CEF;COPTIC COMBINING NI ABOVE;Mn;230;NSM;;;;;N;;;;;
+2CF0;COPTIC COMBINING SPIRITUS ASPER;Mn;230;NSM;;;;;N;;;;;
+2CF1;COPTIC COMBINING SPIRITUS LENIS;Mn;230;NSM;;;;;N;;;;;
+2CF9;COPTIC OLD NUBIAN FULL STOP;Po;0;ON;;;;;N;;;;;
+2CFA;COPTIC OLD NUBIAN DIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;;
+2CFB;COPTIC OLD NUBIAN INDIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;;
+2CFC;COPTIC OLD NUBIAN VERSE DIVIDER;Po;0;ON;;;;;N;;;;;
+2CFD;COPTIC FRACTION ONE HALF;No;0;ON;;;;1/2;N;;;;;
+2CFE;COPTIC FULL STOP;Po;0;ON;;;;;N;;;;;
+2CFF;COPTIC MORPHOLOGICAL DIVIDER;Po;0;ON;;;;;N;;;;;
+2D00;GEORGIAN SMALL LETTER AN;Ll;0;L;;;;;N;;;10A0;;10A0
+2D01;GEORGIAN SMALL LETTER BAN;Ll;0;L;;;;;N;;;10A1;;10A1
+2D02;GEORGIAN SMALL LETTER GAN;Ll;0;L;;;;;N;;;10A2;;10A2
+2D03;GEORGIAN SMALL LETTER DON;Ll;0;L;;;;;N;;;10A3;;10A3
+2D04;GEORGIAN SMALL LETTER EN;Ll;0;L;;;;;N;;;10A4;;10A4
+2D05;GEORGIAN SMALL LETTER VIN;Ll;0;L;;;;;N;;;10A5;;10A5
+2D06;GEORGIAN SMALL LETTER ZEN;Ll;0;L;;;;;N;;;10A6;;10A6
+2D07;GEORGIAN SMALL LETTER TAN;Ll;0;L;;;;;N;;;10A7;;10A7
+2D08;GEORGIAN SMALL LETTER IN;Ll;0;L;;;;;N;;;10A8;;10A8
+2D09;GEORGIAN SMALL LETTER KAN;Ll;0;L;;;;;N;;;10A9;;10A9
+2D0A;GEORGIAN SMALL LETTER LAS;Ll;0;L;;;;;N;;;10AA;;10AA
+2D0B;GEORGIAN SMALL LETTER MAN;Ll;0;L;;;;;N;;;10AB;;10AB
+2D0C;GEORGIAN SMALL LETTER NAR;Ll;0;L;;;;;N;;;10AC;;10AC
+2D0D;GEORGIAN SMALL LETTER ON;Ll;0;L;;;;;N;;;10AD;;10AD
+2D0E;GEORGIAN SMALL LETTER PAR;Ll;0;L;;;;;N;;;10AE;;10AE
+2D0F;GEORGIAN SMALL LETTER ZHAR;Ll;0;L;;;;;N;;;10AF;;10AF
+2D10;GEORGIAN SMALL LETTER RAE;Ll;0;L;;;;;N;;;10B0;;10B0
+2D11;GEORGIAN SMALL LETTER SAN;Ll;0;L;;;;;N;;;10B1;;10B1
+2D12;GEORGIAN SMALL LETTER TAR;Ll;0;L;;;;;N;;;10B2;;10B2
+2D13;GEORGIAN SMALL LETTER UN;Ll;0;L;;;;;N;;;10B3;;10B3
+2D14;GEORGIAN SMALL LETTER PHAR;Ll;0;L;;;;;N;;;10B4;;10B4
+2D15;GEORGIAN SMALL LETTER KHAR;Ll;0;L;;;;;N;;;10B5;;10B5
+2D16;GEORGIAN SMALL LETTER GHAN;Ll;0;L;;;;;N;;;10B6;;10B6
+2D17;GEORGIAN SMALL LETTER QAR;Ll;0;L;;;;;N;;;10B7;;10B7
+2D18;GEORGIAN SMALL LETTER SHIN;Ll;0;L;;;;;N;;;10B8;;10B8
+2D19;GEORGIAN SMALL LETTER CHIN;Ll;0;L;;;;;N;;;10B9;;10B9
+2D1A;GEORGIAN SMALL LETTER CAN;Ll;0;L;;;;;N;;;10BA;;10BA
+2D1B;GEORGIAN SMALL LETTER JIL;Ll;0;L;;;;;N;;;10BB;;10BB
+2D1C;GEORGIAN SMALL LETTER CIL;Ll;0;L;;;;;N;;;10BC;;10BC
+2D1D;GEORGIAN SMALL LETTER CHAR;Ll;0;L;;;;;N;;;10BD;;10BD
+2D1E;GEORGIAN SMALL LETTER XAN;Ll;0;L;;;;;N;;;10BE;;10BE
+2D1F;GEORGIAN SMALL LETTER JHAN;Ll;0;L;;;;;N;;;10BF;;10BF
+2D20;GEORGIAN SMALL LETTER HAE;Ll;0;L;;;;;N;;;10C0;;10C0
+2D21;GEORGIAN SMALL LETTER HE;Ll;0;L;;;;;N;;;10C1;;10C1
+2D22;GEORGIAN SMALL LETTER HIE;Ll;0;L;;;;;N;;;10C2;;10C2
+2D23;GEORGIAN SMALL LETTER WE;Ll;0;L;;;;;N;;;10C3;;10C3
+2D24;GEORGIAN SMALL LETTER HAR;Ll;0;L;;;;;N;;;10C4;;10C4
+2D25;GEORGIAN SMALL LETTER HOE;Ll;0;L;;;;;N;;;10C5;;10C5
+2D30;TIFINAGH LETTER YA;Lo;0;L;;;;;N;;;;;
+2D31;TIFINAGH LETTER YAB;Lo;0;L;;;;;N;;;;;
+2D32;TIFINAGH LETTER YABH;Lo;0;L;;;;;N;;;;;
+2D33;TIFINAGH LETTER YAG;Lo;0;L;;;;;N;;;;;
+2D34;TIFINAGH LETTER YAGHH;Lo;0;L;;;;;N;;;;;
+2D35;TIFINAGH LETTER BERBER ACADEMY YAJ;Lo;0;L;;;;;N;;;;;
+2D36;TIFINAGH LETTER YAJ;Lo;0;L;;;;;N;;;;;
+2D37;TIFINAGH LETTER YAD;Lo;0;L;;;;;N;;;;;
+2D38;TIFINAGH LETTER YADH;Lo;0;L;;;;;N;;;;;
+2D39;TIFINAGH LETTER YADD;Lo;0;L;;;;;N;;;;;
+2D3A;TIFINAGH LETTER YADDH;Lo;0;L;;;;;N;;;;;
+2D3B;TIFINAGH LETTER YEY;Lo;0;L;;;;;N;;;;;
+2D3C;TIFINAGH LETTER YAF;Lo;0;L;;;;;N;;;;;
+2D3D;TIFINAGH LETTER YAK;Lo;0;L;;;;;N;;;;;
+2D3E;TIFINAGH LETTER TUAREG YAK;Lo;0;L;;;;;N;;;;;
+2D3F;TIFINAGH LETTER YAKHH;Lo;0;L;;;;;N;;;;;
+2D40;TIFINAGH LETTER YAH;Lo;0;L;;;;;N;;;;;
+2D41;TIFINAGH LETTER BERBER ACADEMY YAH;Lo;0;L;;;;;N;;;;;
+2D42;TIFINAGH LETTER TUAREG YAH;Lo;0;L;;;;;N;;;;;
+2D43;TIFINAGH LETTER YAHH;Lo;0;L;;;;;N;;;;;
+2D44;TIFINAGH LETTER YAA;Lo;0;L;;;;;N;;;;;
+2D45;TIFINAGH LETTER YAKH;Lo;0;L;;;;;N;;;;;
+2D46;TIFINAGH LETTER TUAREG YAKH;Lo;0;L;;;;;N;;;;;
+2D47;TIFINAGH LETTER YAQ;Lo;0;L;;;;;N;;;;;
+2D48;TIFINAGH LETTER TUAREG YAQ;Lo;0;L;;;;;N;;;;;
+2D49;TIFINAGH LETTER YI;Lo;0;L;;;;;N;;;;;
+2D4A;TIFINAGH LETTER YAZH;Lo;0;L;;;;;N;;;;;
+2D4B;TIFINAGH LETTER AHAGGAR YAZH;Lo;0;L;;;;;N;;;;;
+2D4C;TIFINAGH LETTER TUAREG YAZH;Lo;0;L;;;;;N;;;;;
+2D4D;TIFINAGH LETTER YAL;Lo;0;L;;;;;N;;;;;
+2D4E;TIFINAGH LETTER YAM;Lo;0;L;;;;;N;;;;;
+2D4F;TIFINAGH LETTER YAN;Lo;0;L;;;;;N;;;;;
+2D50;TIFINAGH LETTER TUAREG YAGN;Lo;0;L;;;;;N;;;;;
+2D51;TIFINAGH LETTER TUAREG YANG;Lo;0;L;;;;;N;;;;;
+2D52;TIFINAGH LETTER YAP;Lo;0;L;;;;;N;;;;;
+2D53;TIFINAGH LETTER YU;Lo;0;L;;;;;N;;;;;
+2D54;TIFINAGH LETTER YAR;Lo;0;L;;;;;N;;;;;
+2D55;TIFINAGH LETTER YARR;Lo;0;L;;;;;N;;;;;
+2D56;TIFINAGH LETTER YAGH;Lo;0;L;;;;;N;;;;;
+2D57;TIFINAGH LETTER TUAREG YAGH;Lo;0;L;;;;;N;;;;;
+2D58;TIFINAGH LETTER AYER YAGH;Lo;0;L;;;;;N;;;;;
+2D59;TIFINAGH LETTER YAS;Lo;0;L;;;;;N;;;;;
+2D5A;TIFINAGH LETTER YASS;Lo;0;L;;;;;N;;;;;
+2D5B;TIFINAGH LETTER YASH;Lo;0;L;;;;;N;;;;;
+2D5C;TIFINAGH LETTER YAT;Lo;0;L;;;;;N;;;;;
+2D5D;TIFINAGH LETTER YATH;Lo;0;L;;;;;N;;;;;
+2D5E;TIFINAGH LETTER YACH;Lo;0;L;;;;;N;;;;;
+2D5F;TIFINAGH LETTER YATT;Lo;0;L;;;;;N;;;;;
+2D60;TIFINAGH LETTER YAV;Lo;0;L;;;;;N;;;;;
+2D61;TIFINAGH LETTER YAW;Lo;0;L;;;;;N;;;;;
+2D62;TIFINAGH LETTER YAY;Lo;0;L;;;;;N;;;;;
+2D63;TIFINAGH LETTER YAZ;Lo;0;L;;;;;N;;;;;
+2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;;
+2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;;
+2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L;<super> 2D61;;;;N;;;;;
+2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;;
+2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;;
+2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;;
+2D83;ETHIOPIC SYLLABLE SOA;Lo;0;L;;;;;N;;;;;
+2D84;ETHIOPIC SYLLABLE SHOA;Lo;0;L;;;;;N;;;;;
+2D85;ETHIOPIC SYLLABLE BOA;Lo;0;L;;;;;N;;;;;
+2D86;ETHIOPIC SYLLABLE TOA;Lo;0;L;;;;;N;;;;;
+2D87;ETHIOPIC SYLLABLE COA;Lo;0;L;;;;;N;;;;;
+2D88;ETHIOPIC SYLLABLE NOA;Lo;0;L;;;;;N;;;;;
+2D89;ETHIOPIC SYLLABLE NYOA;Lo;0;L;;;;;N;;;;;
+2D8A;ETHIOPIC SYLLABLE GLOTTAL OA;Lo;0;L;;;;;N;;;;;
+2D8B;ETHIOPIC SYLLABLE ZOA;Lo;0;L;;;;;N;;;;;
+2D8C;ETHIOPIC SYLLABLE DOA;Lo;0;L;;;;;N;;;;;
+2D8D;ETHIOPIC SYLLABLE DDOA;Lo;0;L;;;;;N;;;;;
+2D8E;ETHIOPIC SYLLABLE JOA;Lo;0;L;;;;;N;;;;;
+2D8F;ETHIOPIC SYLLABLE THOA;Lo;0;L;;;;;N;;;;;
+2D90;ETHIOPIC SYLLABLE CHOA;Lo;0;L;;;;;N;;;;;
+2D91;ETHIOPIC SYLLABLE PHOA;Lo;0;L;;;;;N;;;;;
+2D92;ETHIOPIC SYLLABLE POA;Lo;0;L;;;;;N;;;;;
+2D93;ETHIOPIC SYLLABLE GGWA;Lo;0;L;;;;;N;;;;;
+2D94;ETHIOPIC SYLLABLE GGWI;Lo;0;L;;;;;N;;;;;
+2D95;ETHIOPIC SYLLABLE GGWEE;Lo;0;L;;;;;N;;;;;
+2D96;ETHIOPIC SYLLABLE GGWE;Lo;0;L;;;;;N;;;;;
+2DA0;ETHIOPIC SYLLABLE SSA;Lo;0;L;;;;;N;;;;;
+2DA1;ETHIOPIC SYLLABLE SSU;Lo;0;L;;;;;N;;;;;
+2DA2;ETHIOPIC SYLLABLE SSI;Lo;0;L;;;;;N;;;;;
+2DA3;ETHIOPIC SYLLABLE SSAA;Lo;0;L;;;;;N;;;;;
+2DA4;ETHIOPIC SYLLABLE SSEE;Lo;0;L;;;;;N;;;;;
+2DA5;ETHIOPIC SYLLABLE SSE;Lo;0;L;;;;;N;;;;;
+2DA6;ETHIOPIC SYLLABLE SSO;Lo;0;L;;;;;N;;;;;
+2DA8;ETHIOPIC SYLLABLE CCA;Lo;0;L;;;;;N;;;;;
+2DA9;ETHIOPIC SYLLABLE CCU;Lo;0;L;;;;;N;;;;;
+2DAA;ETHIOPIC SYLLABLE CCI;Lo;0;L;;;;;N;;;;;
+2DAB;ETHIOPIC SYLLABLE CCAA;Lo;0;L;;;;;N;;;;;
+2DAC;ETHIOPIC SYLLABLE CCEE;Lo;0;L;;;;;N;;;;;
+2DAD;ETHIOPIC SYLLABLE CCE;Lo;0;L;;;;;N;;;;;
+2DAE;ETHIOPIC SYLLABLE CCO;Lo;0;L;;;;;N;;;;;
+2DB0;ETHIOPIC SYLLABLE ZZA;Lo;0;L;;;;;N;;;;;
+2DB1;ETHIOPIC SYLLABLE ZZU;Lo;0;L;;;;;N;;;;;
+2DB2;ETHIOPIC SYLLABLE ZZI;Lo;0;L;;;;;N;;;;;
+2DB3;ETHIOPIC SYLLABLE ZZAA;Lo;0;L;;;;;N;;;;;
+2DB4;ETHIOPIC SYLLABLE ZZEE;Lo;0;L;;;;;N;;;;;
+2DB5;ETHIOPIC SYLLABLE ZZE;Lo;0;L;;;;;N;;;;;
+2DB6;ETHIOPIC SYLLABLE ZZO;Lo;0;L;;;;;N;;;;;
+2DB8;ETHIOPIC SYLLABLE CCHA;Lo;0;L;;;;;N;;;;;
+2DB9;ETHIOPIC SYLLABLE CCHU;Lo;0;L;;;;;N;;;;;
+2DBA;ETHIOPIC SYLLABLE CCHI;Lo;0;L;;;;;N;;;;;
+2DBB;ETHIOPIC SYLLABLE CCHAA;Lo;0;L;;;;;N;;;;;
+2DBC;ETHIOPIC SYLLABLE CCHEE;Lo;0;L;;;;;N;;;;;
+2DBD;ETHIOPIC SYLLABLE CCHE;Lo;0;L;;;;;N;;;;;
+2DBE;ETHIOPIC SYLLABLE CCHO;Lo;0;L;;;;;N;;;;;
+2DC0;ETHIOPIC SYLLABLE QYA;Lo;0;L;;;;;N;;;;;
+2DC1;ETHIOPIC SYLLABLE QYU;Lo;0;L;;;;;N;;;;;
+2DC2;ETHIOPIC SYLLABLE QYI;Lo;0;L;;;;;N;;;;;
+2DC3;ETHIOPIC SYLLABLE QYAA;Lo;0;L;;;;;N;;;;;
+2DC4;ETHIOPIC SYLLABLE QYEE;Lo;0;L;;;;;N;;;;;
+2DC5;ETHIOPIC SYLLABLE QYE;Lo;0;L;;;;;N;;;;;
+2DC6;ETHIOPIC SYLLABLE QYO;Lo;0;L;;;;;N;;;;;
+2DC8;ETHIOPIC SYLLABLE KYA;Lo;0;L;;;;;N;;;;;
+2DC9;ETHIOPIC SYLLABLE KYU;Lo;0;L;;;;;N;;;;;
+2DCA;ETHIOPIC SYLLABLE KYI;Lo;0;L;;;;;N;;;;;
+2DCB;ETHIOPIC SYLLABLE KYAA;Lo;0;L;;;;;N;;;;;
+2DCC;ETHIOPIC SYLLABLE KYEE;Lo;0;L;;;;;N;;;;;
+2DCD;ETHIOPIC SYLLABLE KYE;Lo;0;L;;;;;N;;;;;
+2DCE;ETHIOPIC SYLLABLE KYO;Lo;0;L;;;;;N;;;;;
+2DD0;ETHIOPIC SYLLABLE XYA;Lo;0;L;;;;;N;;;;;
+2DD1;ETHIOPIC SYLLABLE XYU;Lo;0;L;;;;;N;;;;;
+2DD2;ETHIOPIC SYLLABLE XYI;Lo;0;L;;;;;N;;;;;
+2DD3;ETHIOPIC SYLLABLE XYAA;Lo;0;L;;;;;N;;;;;
+2DD4;ETHIOPIC SYLLABLE XYEE;Lo;0;L;;;;;N;;;;;
+2DD5;ETHIOPIC SYLLABLE XYE;Lo;0;L;;;;;N;;;;;
+2DD6;ETHIOPIC SYLLABLE XYO;Lo;0;L;;;;;N;;;;;
+2DD8;ETHIOPIC SYLLABLE GYA;Lo;0;L;;;;;N;;;;;
+2DD9;ETHIOPIC SYLLABLE GYU;Lo;0;L;;;;;N;;;;;
+2DDA;ETHIOPIC SYLLABLE GYI;Lo;0;L;;;;;N;;;;;
+2DDB;ETHIOPIC SYLLABLE GYAA;Lo;0;L;;;;;N;;;;;
+2DDC;ETHIOPIC SYLLABLE GYEE;Lo;0;L;;;;;N;;;;;
+2DDD;ETHIOPIC SYLLABLE GYE;Lo;0;L;;;;;N;;;;;
+2DDE;ETHIOPIC SYLLABLE GYO;Lo;0;L;;;;;N;;;;;
+2DE0;COMBINING CYRILLIC LETTER BE;Mn;230;NSM;;;;;N;;;;;
+2DE1;COMBINING CYRILLIC LETTER VE;Mn;230;NSM;;;;;N;;;;;
+2DE2;COMBINING CYRILLIC LETTER GHE;Mn;230;NSM;;;;;N;;;;;
+2DE3;COMBINING CYRILLIC LETTER DE;Mn;230;NSM;;;;;N;;;;;
+2DE4;COMBINING CYRILLIC LETTER ZHE;Mn;230;NSM;;;;;N;;;;;
+2DE5;COMBINING CYRILLIC LETTER ZE;Mn;230;NSM;;;;;N;;;;;
+2DE6;COMBINING CYRILLIC LETTER KA;Mn;230;NSM;;;;;N;;;;;
+2DE7;COMBINING CYRILLIC LETTER EL;Mn;230;NSM;;;;;N;;;;;
+2DE8;COMBINING CYRILLIC LETTER EM;Mn;230;NSM;;;;;N;;;;;
+2DE9;COMBINING CYRILLIC LETTER EN;Mn;230;NSM;;;;;N;;;;;
+2DEA;COMBINING CYRILLIC LETTER O;Mn;230;NSM;;;;;N;;;;;
+2DEB;COMBINING CYRILLIC LETTER PE;Mn;230;NSM;;;;;N;;;;;
+2DEC;COMBINING CYRILLIC LETTER ER;Mn;230;NSM;;;;;N;;;;;
+2DED;COMBINING CYRILLIC LETTER ES;Mn;230;NSM;;;;;N;;;;;
+2DEE;COMBINING CYRILLIC LETTER TE;Mn;230;NSM;;;;;N;;;;;
+2DEF;COMBINING CYRILLIC LETTER HA;Mn;230;NSM;;;;;N;;;;;
+2DF0;COMBINING CYRILLIC LETTER TSE;Mn;230;NSM;;;;;N;;;;;
+2DF1;COMBINING CYRILLIC LETTER CHE;Mn;230;NSM;;;;;N;;;;;
+2DF2;COMBINING CYRILLIC LETTER SHA;Mn;230;NSM;;;;;N;;;;;
+2DF3;COMBINING CYRILLIC LETTER SHCHA;Mn;230;NSM;;;;;N;;;;;
+2DF4;COMBINING CYRILLIC LETTER FITA;Mn;230;NSM;;;;;N;;;;;
+2DF5;COMBINING CYRILLIC LETTER ES-TE;Mn;230;NSM;;;;;N;;;;;
+2DF6;COMBINING CYRILLIC LETTER A;Mn;230;NSM;;;;;N;;;;;
+2DF7;COMBINING CYRILLIC LETTER IE;Mn;230;NSM;;;;;N;;;;;
+2DF8;COMBINING CYRILLIC LETTER DJERV;Mn;230;NSM;;;;;N;;;;;
+2DF9;COMBINING CYRILLIC LETTER MONOGRAPH UK;Mn;230;NSM;;;;;N;;;;;
+2DFA;COMBINING CYRILLIC LETTER YAT;Mn;230;NSM;;;;;N;;;;;
+2DFB;COMBINING CYRILLIC LETTER YU;Mn;230;NSM;;;;;N;;;;;
+2DFC;COMBINING CYRILLIC LETTER IOTIFIED A;Mn;230;NSM;;;;;N;;;;;
+2DFD;COMBINING CYRILLIC LETTER LITTLE YUS;Mn;230;NSM;;;;;N;;;;;
+2DFE;COMBINING CYRILLIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;;
+2DFF;COMBINING CYRILLIC LETTER IOTIFIED BIG YUS;Mn;230;NSM;;;;;N;;;;;
+2E00;RIGHT ANGLE SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;;
+2E01;RIGHT ANGLE DOTTED SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;;
+2E02;LEFT SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;;
+2E03;RIGHT SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;;
+2E04;LEFT DOTTED SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;;
+2E05;RIGHT DOTTED SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;;
+2E06;RAISED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;;
+2E07;RAISED DOTTED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;;
+2E08;DOTTED TRANSPOSITION MARKER;Po;0;ON;;;;;N;;;;;
+2E09;LEFT TRANSPOSITION BRACKET;Pi;0;ON;;;;;Y;;;;;
+2E0A;RIGHT TRANSPOSITION BRACKET;Pf;0;ON;;;;;Y;;;;;
+2E0B;RAISED SQUARE;Po;0;ON;;;;;N;;;;;
+2E0C;LEFT RAISED OMISSION BRACKET;Pi;0;ON;;;;;Y;;;;;
+2E0D;RIGHT RAISED OMISSION BRACKET;Pf;0;ON;;;;;Y;;;;;
+2E0E;EDITORIAL CORONIS;Po;0;ON;;;;;N;;;;;
+2E0F;PARAGRAPHOS;Po;0;ON;;;;;N;;;;;
+2E10;FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;;
+2E11;REVERSED FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;;
+2E12;HYPODIASTOLE;Po;0;ON;;;;;N;;;;;
+2E13;DOTTED OBELOS;Po;0;ON;;;;;N;;;;;
+2E14;DOWNWARDS ANCORA;Po;0;ON;;;;;N;;;;;
+2E15;UPWARDS ANCORA;Po;0;ON;;;;;N;;;;;
+2E16;DOTTED RIGHT-POINTING ANGLE;Po;0;ON;;;;;N;;;;;
+2E17;DOUBLE OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;;
+2E18;INVERTED INTERROBANG;Po;0;ON;;;;;N;;;;;
+2E19;PALM BRANCH;Po;0;ON;;;;;N;;;;;
+2E1A;HYPHEN WITH DIAERESIS;Pd;0;ON;;;;;N;;;;;
+2E1B;TILDE WITH RING ABOVE;Po;0;ON;;;;;N;;;;;
+2E1C;LEFT LOW PARAPHRASE BRACKET;Pi;0;ON;;;;;Y;;;;;
+2E1D;RIGHT LOW PARAPHRASE BRACKET;Pf;0;ON;;;;;Y;;;;;
+2E1E;TILDE WITH DOT ABOVE;Po;0;ON;;;;;N;;;;;
+2E1F;TILDE WITH DOT BELOW;Po;0;ON;;;;;N;;;;;
+2E20;LEFT VERTICAL BAR WITH QUILL;Pi;0;ON;;;;;Y;;;;;
+2E21;RIGHT VERTICAL BAR WITH QUILL;Pf;0;ON;;;;;Y;;;;;
+2E22;TOP LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;;
+2E23;TOP RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;;
+2E24;BOTTOM LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;;
+2E25;BOTTOM RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;;
+2E26;LEFT SIDEWAYS U BRACKET;Ps;0;ON;;;;;Y;;;;;
+2E27;RIGHT SIDEWAYS U BRACKET;Pe;0;ON;;;;;Y;;;;;
+2E28;LEFT DOUBLE PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
+2E29;RIGHT DOUBLE PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
+2E2A;TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+2E2B;ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;;
+2E2C;SQUARED FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+2E2D;FIVE DOT MARK;Po;0;ON;;;;;N;;;;;
+2E2E;REVERSED QUESTION MARK;Po;0;ON;;;;;N;;;;;
+2E2F;VERTICAL TILDE;Lm;0;ON;;;;;N;;;;;
+2E30;RING POINT;Po;0;ON;;;;;N;;;;;
+2E31;WORD SEPARATOR MIDDLE DOT;Po;0;ON;;;;;N;;;;;
+2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;;
+2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;;
+2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;;
+2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;;
+2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;;
+2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;;
+2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;;
+2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;;
+2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;;
+2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;;
+2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;;
+2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;;
+2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;;
+2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;;
+2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;;
+2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;;
+2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;;
+2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;;
+2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;;
+2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;;
+2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;;
+2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;;
+2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;;
+2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;;
+2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;;
+2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;;
+2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;;
+2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;;
+2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;;
+2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;;
+2E9F;CJK RADICAL MOTHER;So;0;ON;<compat> 6BCD;;;;N;;;;;
+2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;;
+2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;;
+2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;;
+2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;;
+2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;;
+2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;;
+2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;;
+2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;;
+2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;;
+2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;;
+2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;;
+2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;;
+2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;;
+2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;;
+2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;;
+2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;;
+2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;;
+2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;;
+2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;;
+2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;;
+2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;;
+2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;;
+2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;;
+2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;;
+2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;;
+2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;;
+2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;;
+2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;;
+2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;;
+2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;;
+2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;;
+2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;;
+2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;;
+2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;;
+2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;;
+2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;;
+2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;;
+2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;;
+2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;;
+2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;;
+2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;;
+2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;;
+2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;;
+2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;;
+2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;;
+2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;;
+2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;;
+2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;;
+2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;;
+2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;;
+2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;;
+2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;;
+2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;;
+2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;;
+2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;;
+2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;;
+2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;;
+2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;;
+2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;;
+2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;;
+2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;;
+2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;;
+2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;;
+2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;;
+2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;;
+2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;;
+2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;;
+2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;;
+2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;;
+2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;;
+2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;;
+2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;;
+2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;;
+2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;;
+2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;;
+2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;;
+2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;;
+2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;;
+2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;;
+2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;;
+2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;;
+2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;;
+2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;;
+2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON;<compat> 9F9F;;;;N;;;;;
+2F00;KANGXI RADICAL ONE;So;0;ON;<compat> 4E00;;;;N;;;;;
+2F01;KANGXI RADICAL LINE;So;0;ON;<compat> 4E28;;;;N;;;;;
+2F02;KANGXI RADICAL DOT;So;0;ON;<compat> 4E36;;;;N;;;;;
+2F03;KANGXI RADICAL SLASH;So;0;ON;<compat> 4E3F;;;;N;;;;;
+2F04;KANGXI RADICAL SECOND;So;0;ON;<compat> 4E59;;;;N;;;;;
+2F05;KANGXI RADICAL HOOK;So;0;ON;<compat> 4E85;;;;N;;;;;
+2F06;KANGXI RADICAL TWO;So;0;ON;<compat> 4E8C;;;;N;;;;;
+2F07;KANGXI RADICAL LID;So;0;ON;<compat> 4EA0;;;;N;;;;;
+2F08;KANGXI RADICAL MAN;So;0;ON;<compat> 4EBA;;;;N;;;;;
+2F09;KANGXI RADICAL LEGS;So;0;ON;<compat> 513F;;;;N;;;;;
+2F0A;KANGXI RADICAL ENTER;So;0;ON;<compat> 5165;;;;N;;;;;
+2F0B;KANGXI RADICAL EIGHT;So;0;ON;<compat> 516B;;;;N;;;;;
+2F0C;KANGXI RADICAL DOWN BOX;So;0;ON;<compat> 5182;;;;N;;;;;
+2F0D;KANGXI RADICAL COVER;So;0;ON;<compat> 5196;;;;N;;;;;
+2F0E;KANGXI RADICAL ICE;So;0;ON;<compat> 51AB;;;;N;;;;;
+2F0F;KANGXI RADICAL TABLE;So;0;ON;<compat> 51E0;;;;N;;;;;
+2F10;KANGXI RADICAL OPEN BOX;So;0;ON;<compat> 51F5;;;;N;;;;;
+2F11;KANGXI RADICAL KNIFE;So;0;ON;<compat> 5200;;;;N;;;;;
+2F12;KANGXI RADICAL POWER;So;0;ON;<compat> 529B;;;;N;;;;;
+2F13;KANGXI RADICAL WRAP;So;0;ON;<compat> 52F9;;;;N;;;;;
+2F14;KANGXI RADICAL SPOON;So;0;ON;<compat> 5315;;;;N;;;;;
+2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON;<compat> 531A;;;;N;;;;;
+2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON;<compat> 5338;;;;N;;;;;
+2F17;KANGXI RADICAL TEN;So;0;ON;<compat> 5341;;;;N;;;;;
+2F18;KANGXI RADICAL DIVINATION;So;0;ON;<compat> 535C;;;;N;;;;;
+2F19;KANGXI RADICAL SEAL;So;0;ON;<compat> 5369;;;;N;;;;;
+2F1A;KANGXI RADICAL CLIFF;So;0;ON;<compat> 5382;;;;N;;;;;
+2F1B;KANGXI RADICAL PRIVATE;So;0;ON;<compat> 53B6;;;;N;;;;;
+2F1C;KANGXI RADICAL AGAIN;So;0;ON;<compat> 53C8;;;;N;;;;;
+2F1D;KANGXI RADICAL MOUTH;So;0;ON;<compat> 53E3;;;;N;;;;;
+2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON;<compat> 56D7;;;;N;;;;;
+2F1F;KANGXI RADICAL EARTH;So;0;ON;<compat> 571F;;;;N;;;;;
+2F20;KANGXI RADICAL SCHOLAR;So;0;ON;<compat> 58EB;;;;N;;;;;
+2F21;KANGXI RADICAL GO;So;0;ON;<compat> 5902;;;;N;;;;;
+2F22;KANGXI RADICAL GO SLOWLY;So;0;ON;<compat> 590A;;;;N;;;;;
+2F23;KANGXI RADICAL EVENING;So;0;ON;<compat> 5915;;;;N;;;;;
+2F24;KANGXI RADICAL BIG;So;0;ON;<compat> 5927;;;;N;;;;;
+2F25;KANGXI RADICAL WOMAN;So;0;ON;<compat> 5973;;;;N;;;;;
+2F26;KANGXI RADICAL CHILD;So;0;ON;<compat> 5B50;;;;N;;;;;
+2F27;KANGXI RADICAL ROOF;So;0;ON;<compat> 5B80;;;;N;;;;;
+2F28;KANGXI RADICAL INCH;So;0;ON;<compat> 5BF8;;;;N;;;;;
+2F29;KANGXI RADICAL SMALL;So;0;ON;<compat> 5C0F;;;;N;;;;;
+2F2A;KANGXI RADICAL LAME;So;0;ON;<compat> 5C22;;;;N;;;;;
+2F2B;KANGXI RADICAL CORPSE;So;0;ON;<compat> 5C38;;;;N;;;;;
+2F2C;KANGXI RADICAL SPROUT;So;0;ON;<compat> 5C6E;;;;N;;;;;
+2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON;<compat> 5C71;;;;N;;;;;
+2F2E;KANGXI RADICAL RIVER;So;0;ON;<compat> 5DDB;;;;N;;;;;
+2F2F;KANGXI RADICAL WORK;So;0;ON;<compat> 5DE5;;;;N;;;;;
+2F30;KANGXI RADICAL ONESELF;So;0;ON;<compat> 5DF1;;;;N;;;;;
+2F31;KANGXI RADICAL TURBAN;So;0;ON;<compat> 5DFE;;;;N;;;;;
+2F32;KANGXI RADICAL DRY;So;0;ON;<compat> 5E72;;;;N;;;;;
+2F33;KANGXI RADICAL SHORT THREAD;So;0;ON;<compat> 5E7A;;;;N;;;;;
+2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON;<compat> 5E7F;;;;N;;;;;
+2F35;KANGXI RADICAL LONG STRIDE;So;0;ON;<compat> 5EF4;;;;N;;;;;
+2F36;KANGXI RADICAL TWO HANDS;So;0;ON;<compat> 5EFE;;;;N;;;;;
+2F37;KANGXI RADICAL SHOOT;So;0;ON;<compat> 5F0B;;;;N;;;;;
+2F38;KANGXI RADICAL BOW;So;0;ON;<compat> 5F13;;;;N;;;;;
+2F39;KANGXI RADICAL SNOUT;So;0;ON;<compat> 5F50;;;;N;;;;;
+2F3A;KANGXI RADICAL BRISTLE;So;0;ON;<compat> 5F61;;;;N;;;;;
+2F3B;KANGXI RADICAL STEP;So;0;ON;<compat> 5F73;;;;N;;;;;
+2F3C;KANGXI RADICAL HEART;So;0;ON;<compat> 5FC3;;;;N;;;;;
+2F3D;KANGXI RADICAL HALBERD;So;0;ON;<compat> 6208;;;;N;;;;;
+2F3E;KANGXI RADICAL DOOR;So;0;ON;<compat> 6236;;;;N;;;;;
+2F3F;KANGXI RADICAL HAND;So;0;ON;<compat> 624B;;;;N;;;;;
+2F40;KANGXI RADICAL BRANCH;So;0;ON;<compat> 652F;;;;N;;;;;
+2F41;KANGXI RADICAL RAP;So;0;ON;<compat> 6534;;;;N;;;;;
+2F42;KANGXI RADICAL SCRIPT;So;0;ON;<compat> 6587;;;;N;;;;;
+2F43;KANGXI RADICAL DIPPER;So;0;ON;<compat> 6597;;;;N;;;;;
+2F44;KANGXI RADICAL AXE;So;0;ON;<compat> 65A4;;;;N;;;;;
+2F45;KANGXI RADICAL SQUARE;So;0;ON;<compat> 65B9;;;;N;;;;;
+2F46;KANGXI RADICAL NOT;So;0;ON;<compat> 65E0;;;;N;;;;;
+2F47;KANGXI RADICAL SUN;So;0;ON;<compat> 65E5;;;;N;;;;;
+2F48;KANGXI RADICAL SAY;So;0;ON;<compat> 66F0;;;;N;;;;;
+2F49;KANGXI RADICAL MOON;So;0;ON;<compat> 6708;;;;N;;;;;
+2F4A;KANGXI RADICAL TREE;So;0;ON;<compat> 6728;;;;N;;;;;
+2F4B;KANGXI RADICAL LACK;So;0;ON;<compat> 6B20;;;;N;;;;;
+2F4C;KANGXI RADICAL STOP;So;0;ON;<compat> 6B62;;;;N;;;;;
+2F4D;KANGXI RADICAL DEATH;So;0;ON;<compat> 6B79;;;;N;;;;;
+2F4E;KANGXI RADICAL WEAPON;So;0;ON;<compat> 6BB3;;;;N;;;;;
+2F4F;KANGXI RADICAL DO NOT;So;0;ON;<compat> 6BCB;;;;N;;;;;
+2F50;KANGXI RADICAL COMPARE;So;0;ON;<compat> 6BD4;;;;N;;;;;
+2F51;KANGXI RADICAL FUR;So;0;ON;<compat> 6BDB;;;;N;;;;;
+2F52;KANGXI RADICAL CLAN;So;0;ON;<compat> 6C0F;;;;N;;;;;
+2F53;KANGXI RADICAL STEAM;So;0;ON;<compat> 6C14;;;;N;;;;;
+2F54;KANGXI RADICAL WATER;So;0;ON;<compat> 6C34;;;;N;;;;;
+2F55;KANGXI RADICAL FIRE;So;0;ON;<compat> 706B;;;;N;;;;;
+2F56;KANGXI RADICAL CLAW;So;0;ON;<compat> 722A;;;;N;;;;;
+2F57;KANGXI RADICAL FATHER;So;0;ON;<compat> 7236;;;;N;;;;;
+2F58;KANGXI RADICAL DOUBLE X;So;0;ON;<compat> 723B;;;;N;;;;;
+2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON;<compat> 723F;;;;N;;;;;
+2F5A;KANGXI RADICAL SLICE;So;0;ON;<compat> 7247;;;;N;;;;;
+2F5B;KANGXI RADICAL FANG;So;0;ON;<compat> 7259;;;;N;;;;;
+2F5C;KANGXI RADICAL COW;So;0;ON;<compat> 725B;;;;N;;;;;
+2F5D;KANGXI RADICAL DOG;So;0;ON;<compat> 72AC;;;;N;;;;;
+2F5E;KANGXI RADICAL PROFOUND;So;0;ON;<compat> 7384;;;;N;;;;;
+2F5F;KANGXI RADICAL JADE;So;0;ON;<compat> 7389;;;;N;;;;;
+2F60;KANGXI RADICAL MELON;So;0;ON;<compat> 74DC;;;;N;;;;;
+2F61;KANGXI RADICAL TILE;So;0;ON;<compat> 74E6;;;;N;;;;;
+2F62;KANGXI RADICAL SWEET;So;0;ON;<compat> 7518;;;;N;;;;;
+2F63;KANGXI RADICAL LIFE;So;0;ON;<compat> 751F;;;;N;;;;;
+2F64;KANGXI RADICAL USE;So;0;ON;<compat> 7528;;;;N;;;;;
+2F65;KANGXI RADICAL FIELD;So;0;ON;<compat> 7530;;;;N;;;;;
+2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON;<compat> 758B;;;;N;;;;;
+2F67;KANGXI RADICAL SICKNESS;So;0;ON;<compat> 7592;;;;N;;;;;
+2F68;KANGXI RADICAL DOTTED TENT;So;0;ON;<compat> 7676;;;;N;;;;;
+2F69;KANGXI RADICAL WHITE;So;0;ON;<compat> 767D;;;;N;;;;;
+2F6A;KANGXI RADICAL SKIN;So;0;ON;<compat> 76AE;;;;N;;;;;
+2F6B;KANGXI RADICAL DISH;So;0;ON;<compat> 76BF;;;;N;;;;;
+2F6C;KANGXI RADICAL EYE;So;0;ON;<compat> 76EE;;;;N;;;;;
+2F6D;KANGXI RADICAL SPEAR;So;0;ON;<compat> 77DB;;;;N;;;;;
+2F6E;KANGXI RADICAL ARROW;So;0;ON;<compat> 77E2;;;;N;;;;;
+2F6F;KANGXI RADICAL STONE;So;0;ON;<compat> 77F3;;;;N;;;;;
+2F70;KANGXI RADICAL SPIRIT;So;0;ON;<compat> 793A;;;;N;;;;;
+2F71;KANGXI RADICAL TRACK;So;0;ON;<compat> 79B8;;;;N;;;;;
+2F72;KANGXI RADICAL GRAIN;So;0;ON;<compat> 79BE;;;;N;;;;;
+2F73;KANGXI RADICAL CAVE;So;0;ON;<compat> 7A74;;;;N;;;;;
+2F74;KANGXI RADICAL STAND;So;0;ON;<compat> 7ACB;;;;N;;;;;
+2F75;KANGXI RADICAL BAMBOO;So;0;ON;<compat> 7AF9;;;;N;;;;;
+2F76;KANGXI RADICAL RICE;So;0;ON;<compat> 7C73;;;;N;;;;;
+2F77;KANGXI RADICAL SILK;So;0;ON;<compat> 7CF8;;;;N;;;;;
+2F78;KANGXI RADICAL JAR;So;0;ON;<compat> 7F36;;;;N;;;;;
+2F79;KANGXI RADICAL NET;So;0;ON;<compat> 7F51;;;;N;;;;;
+2F7A;KANGXI RADICAL SHEEP;So;0;ON;<compat> 7F8A;;;;N;;;;;
+2F7B;KANGXI RADICAL FEATHER;So;0;ON;<compat> 7FBD;;;;N;;;;;
+2F7C;KANGXI RADICAL OLD;So;0;ON;<compat> 8001;;;;N;;;;;
+2F7D;KANGXI RADICAL AND;So;0;ON;<compat> 800C;;;;N;;;;;
+2F7E;KANGXI RADICAL PLOW;So;0;ON;<compat> 8012;;;;N;;;;;
+2F7F;KANGXI RADICAL EAR;So;0;ON;<compat> 8033;;;;N;;;;;
+2F80;KANGXI RADICAL BRUSH;So;0;ON;<compat> 807F;;;;N;;;;;
+2F81;KANGXI RADICAL MEAT;So;0;ON;<compat> 8089;;;;N;;;;;
+2F82;KANGXI RADICAL MINISTER;So;0;ON;<compat> 81E3;;;;N;;;;;
+2F83;KANGXI RADICAL SELF;So;0;ON;<compat> 81EA;;;;N;;;;;
+2F84;KANGXI RADICAL ARRIVE;So;0;ON;<compat> 81F3;;;;N;;;;;
+2F85;KANGXI RADICAL MORTAR;So;0;ON;<compat> 81FC;;;;N;;;;;
+2F86;KANGXI RADICAL TONGUE;So;0;ON;<compat> 820C;;;;N;;;;;
+2F87;KANGXI RADICAL OPPOSE;So;0;ON;<compat> 821B;;;;N;;;;;
+2F88;KANGXI RADICAL BOAT;So;0;ON;<compat> 821F;;;;N;;;;;
+2F89;KANGXI RADICAL STOPPING;So;0;ON;<compat> 826E;;;;N;;;;;
+2F8A;KANGXI RADICAL COLOR;So;0;ON;<compat> 8272;;;;N;;;;;
+2F8B;KANGXI RADICAL GRASS;So;0;ON;<compat> 8278;;;;N;;;;;
+2F8C;KANGXI RADICAL TIGER;So;0;ON;<compat> 864D;;;;N;;;;;
+2F8D;KANGXI RADICAL INSECT;So;0;ON;<compat> 866B;;;;N;;;;;
+2F8E;KANGXI RADICAL BLOOD;So;0;ON;<compat> 8840;;;;N;;;;;
+2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON;<compat> 884C;;;;N;;;;;
+2F90;KANGXI RADICAL CLOTHES;So;0;ON;<compat> 8863;;;;N;;;;;
+2F91;KANGXI RADICAL WEST;So;0;ON;<compat> 897E;;;;N;;;;;
+2F92;KANGXI RADICAL SEE;So;0;ON;<compat> 898B;;;;N;;;;;
+2F93;KANGXI RADICAL HORN;So;0;ON;<compat> 89D2;;;;N;;;;;
+2F94;KANGXI RADICAL SPEECH;So;0;ON;<compat> 8A00;;;;N;;;;;
+2F95;KANGXI RADICAL VALLEY;So;0;ON;<compat> 8C37;;;;N;;;;;
+2F96;KANGXI RADICAL BEAN;So;0;ON;<compat> 8C46;;;;N;;;;;
+2F97;KANGXI RADICAL PIG;So;0;ON;<compat> 8C55;;;;N;;;;;
+2F98;KANGXI RADICAL BADGER;So;0;ON;<compat> 8C78;;;;N;;;;;
+2F99;KANGXI RADICAL SHELL;So;0;ON;<compat> 8C9D;;;;N;;;;;
+2F9A;KANGXI RADICAL RED;So;0;ON;<compat> 8D64;;;;N;;;;;
+2F9B;KANGXI RADICAL RUN;So;0;ON;<compat> 8D70;;;;N;;;;;
+2F9C;KANGXI RADICAL FOOT;So;0;ON;<compat> 8DB3;;;;N;;;;;
+2F9D;KANGXI RADICAL BODY;So;0;ON;<compat> 8EAB;;;;N;;;;;
+2F9E;KANGXI RADICAL CART;So;0;ON;<compat> 8ECA;;;;N;;;;;
+2F9F;KANGXI RADICAL BITTER;So;0;ON;<compat> 8F9B;;;;N;;;;;
+2FA0;KANGXI RADICAL MORNING;So;0;ON;<compat> 8FB0;;;;N;;;;;
+2FA1;KANGXI RADICAL WALK;So;0;ON;<compat> 8FB5;;;;N;;;;;
+2FA2;KANGXI RADICAL CITY;So;0;ON;<compat> 9091;;;;N;;;;;
+2FA3;KANGXI RADICAL WINE;So;0;ON;<compat> 9149;;;;N;;;;;
+2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON;<compat> 91C6;;;;N;;;;;
+2FA5;KANGXI RADICAL VILLAGE;So;0;ON;<compat> 91CC;;;;N;;;;;
+2FA6;KANGXI RADICAL GOLD;So;0;ON;<compat> 91D1;;;;N;;;;;
+2FA7;KANGXI RADICAL LONG;So;0;ON;<compat> 9577;;;;N;;;;;
+2FA8;KANGXI RADICAL GATE;So;0;ON;<compat> 9580;;;;N;;;;;
+2FA9;KANGXI RADICAL MOUND;So;0;ON;<compat> 961C;;;;N;;;;;
+2FAA;KANGXI RADICAL SLAVE;So;0;ON;<compat> 96B6;;;;N;;;;;
+2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON;<compat> 96B9;;;;N;;;;;
+2FAC;KANGXI RADICAL RAIN;So;0;ON;<compat> 96E8;;;;N;;;;;
+2FAD;KANGXI RADICAL BLUE;So;0;ON;<compat> 9751;;;;N;;;;;
+2FAE;KANGXI RADICAL WRONG;So;0;ON;<compat> 975E;;;;N;;;;;
+2FAF;KANGXI RADICAL FACE;So;0;ON;<compat> 9762;;;;N;;;;;
+2FB0;KANGXI RADICAL LEATHER;So;0;ON;<compat> 9769;;;;N;;;;;
+2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON;<compat> 97CB;;;;N;;;;;
+2FB2;KANGXI RADICAL LEEK;So;0;ON;<compat> 97ED;;;;N;;;;;
+2FB3;KANGXI RADICAL SOUND;So;0;ON;<compat> 97F3;;;;N;;;;;
+2FB4;KANGXI RADICAL LEAF;So;0;ON;<compat> 9801;;;;N;;;;;
+2FB5;KANGXI RADICAL WIND;So;0;ON;<compat> 98A8;;;;N;;;;;
+2FB6;KANGXI RADICAL FLY;So;0;ON;<compat> 98DB;;;;N;;;;;
+2FB7;KANGXI RADICAL EAT;So;0;ON;<compat> 98DF;;;;N;;;;;
+2FB8;KANGXI RADICAL HEAD;So;0;ON;<compat> 9996;;;;N;;;;;
+2FB9;KANGXI RADICAL FRAGRANT;So;0;ON;<compat> 9999;;;;N;;;;;
+2FBA;KANGXI RADICAL HORSE;So;0;ON;<compat> 99AC;;;;N;;;;;
+2FBB;KANGXI RADICAL BONE;So;0;ON;<compat> 9AA8;;;;N;;;;;
+2FBC;KANGXI RADICAL TALL;So;0;ON;<compat> 9AD8;;;;N;;;;;
+2FBD;KANGXI RADICAL HAIR;So;0;ON;<compat> 9ADF;;;;N;;;;;
+2FBE;KANGXI RADICAL FIGHT;So;0;ON;<compat> 9B25;;;;N;;;;;
+2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON;<compat> 9B2F;;;;N;;;;;
+2FC0;KANGXI RADICAL CAULDRON;So;0;ON;<compat> 9B32;;;;N;;;;;
+2FC1;KANGXI RADICAL GHOST;So;0;ON;<compat> 9B3C;;;;N;;;;;
+2FC2;KANGXI RADICAL FISH;So;0;ON;<compat> 9B5A;;;;N;;;;;
+2FC3;KANGXI RADICAL BIRD;So;0;ON;<compat> 9CE5;;;;N;;;;;
+2FC4;KANGXI RADICAL SALT;So;0;ON;<compat> 9E75;;;;N;;;;;
+2FC5;KANGXI RADICAL DEER;So;0;ON;<compat> 9E7F;;;;N;;;;;
+2FC6;KANGXI RADICAL WHEAT;So;0;ON;<compat> 9EA5;;;;N;;;;;
+2FC7;KANGXI RADICAL HEMP;So;0;ON;<compat> 9EBB;;;;N;;;;;
+2FC8;KANGXI RADICAL YELLOW;So;0;ON;<compat> 9EC3;;;;N;;;;;
+2FC9;KANGXI RADICAL MILLET;So;0;ON;<compat> 9ECD;;;;N;;;;;
+2FCA;KANGXI RADICAL BLACK;So;0;ON;<compat> 9ED1;;;;N;;;;;
+2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON;<compat> 9EF9;;;;N;;;;;
+2FCC;KANGXI RADICAL FROG;So;0;ON;<compat> 9EFD;;;;N;;;;;
+2FCD;KANGXI RADICAL TRIPOD;So;0;ON;<compat> 9F0E;;;;N;;;;;
+2FCE;KANGXI RADICAL DRUM;So;0;ON;<compat> 9F13;;;;N;;;;;
+2FCF;KANGXI RADICAL RAT;So;0;ON;<compat> 9F20;;;;N;;;;;
+2FD0;KANGXI RADICAL NOSE;So;0;ON;<compat> 9F3B;;;;N;;;;;
+2FD1;KANGXI RADICAL EVEN;So;0;ON;<compat> 9F4A;;;;N;;;;;
+2FD2;KANGXI RADICAL TOOTH;So;0;ON;<compat> 9F52;;;;N;;;;;
+2FD3;KANGXI RADICAL DRAGON;So;0;ON;<compat> 9F8D;;;;N;;;;;
+2FD4;KANGXI RADICAL TURTLE;So;0;ON;<compat> 9F9C;;;;N;;;;;
+2FD5;KANGXI RADICAL FLUTE;So;0;ON;<compat> 9FA0;;;;N;;;;;
+2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;;
+2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;;
+2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;;
+2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;;
+2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;;
+2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;;
+2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;;
+2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;;
+2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;;
+2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;;
+2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;;
+2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;;
+3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
+3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;;
+3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;;
+3003;DITTO MARK;Po;0;ON;;;;;N;;;;;
+3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;;
+3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;;
+3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;;
+3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;;
+3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;;
+3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;;
+300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;;
+300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;;
+300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;;
+300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;;
+300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;;
+300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;;
+3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;;
+3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;;
+3012;POSTAL MARK;So;0;ON;;;;;N;;;;;
+3013;GETA MARK;So;0;ON;;;;;N;;;;;
+3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;;
+3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;;
+3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;;
+3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;;
+3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;;
+3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;;
+301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;;
+301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;;
+301C;WAVE DASH;Pd;0;ON;;;;;N;;;;;
+301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;;
+301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;;
+301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;;
+3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;;
+3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;;
+3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;;
+3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;;
+3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;;
+3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;;
+3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;;
+3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;;
+3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;;
+3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;;
+302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;;
+302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;;
+302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;;
+302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;;
+302E;HANGUL SINGLE DOT TONE MARK;Mn;224;NSM;;;;;N;;;;;
+302F;HANGUL DOUBLE DOT TONE MARK;Mn;224;NSM;;;;;N;;;;;
+3030;WAVY DASH;Pd;0;ON;;;;;N;;;;;
+3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;;
+3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;;
+3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;;
+3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;;
+3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;;
+3036;CIRCLED POSTAL MARK;So;0;ON;<compat> 3012;;;;N;;;;;
+3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;;
+3038;HANGZHOU NUMERAL TEN;Nl;0;L;<compat> 5341;;;10;N;;;;;
+3039;HANGZHOU NUMERAL TWENTY;Nl;0;L;<compat> 5344;;;20;N;;;;;
+303A;HANGZHOU NUMERAL THIRTY;Nl;0;L;<compat> 5345;;;30;N;;;;;
+303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;;
+303C;MASU MARK;Lo;0;L;;;;;N;;;;;
+303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;;
+303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;;
+303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;;
+3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;;
+3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;;
+3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;;
+3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;;
+3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;;
+3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;;
+3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;;
+3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;;
+3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;;
+304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;;
+304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;;
+304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;;
+304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;;
+304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;;
+304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;;
+3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;;
+3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;;
+3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;;
+3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;;
+3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;;
+3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;;
+3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;;
+3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;;
+3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;;
+3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;;
+305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;;
+305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;;
+305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;;
+305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;;
+305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;;
+305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;;
+3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;;
+3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;;
+3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;;
+3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;;
+3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;;
+3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;;
+3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;;
+3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;;
+3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;;
+3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;;
+306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;;
+306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;;
+306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;;
+306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;;
+306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;;
+306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;;
+3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;;
+3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;;
+3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;;
+3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;;
+3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;;
+3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;;
+3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;;
+3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;;
+3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;;
+3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;;
+307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;;
+307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;;
+307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;;
+307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;;
+307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;;
+307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;;
+3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;;
+3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;;
+3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;;
+3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;;
+3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;;
+3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;;
+3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;;
+3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;;
+3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;;
+3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;;
+308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;;
+308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;;
+308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;;
+308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;;
+308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;;
+308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;;
+3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;;
+3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;;
+3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;;
+3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;;
+3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;;
+3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;;
+3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;;
+3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;;
+309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;;
+309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON;<compat> 0020 3099;;;;N;;;;;
+309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON;<compat> 0020 309A;;;;N;;;;;
+309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;;
+309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;;
+309F;HIRAGANA DIGRAPH YORI;Lo;0;L;<vertical> 3088 308A;;;;N;;;;;
+30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;;
+30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;;
+30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;;
+30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;;
+30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;;
+30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;;
+30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;;
+30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;;
+30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;;
+30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;;
+30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;;
+30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;;
+30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;;
+30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;;
+30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;;
+30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;;
+30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;;
+30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;;
+30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;;
+30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;;
+30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;;
+30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;;
+30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;;
+30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;;
+30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;;
+30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;;
+30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;;
+30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;;
+30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;;
+30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;;
+30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;;
+30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;;
+30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;;
+30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;;
+30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;;
+30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;;
+30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;;
+30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;;
+30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;;
+30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;;
+30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;;
+30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;;
+30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;;
+30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;;
+30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;;
+30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;;
+30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;;
+30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;;
+30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;;
+30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;;
+30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;;
+30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;;
+30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;;
+30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;;
+30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;;
+30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;;
+30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;;
+30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;;
+30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;;
+30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;;
+30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;;
+30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;;
+30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;;
+30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;;
+30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;;
+30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;;
+30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;;
+30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;;
+30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;;
+30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;;
+30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;;
+30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;;
+30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;;
+30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;;
+30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;;
+30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;;
+30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;;
+30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;;
+30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;;
+30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;;
+30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;;
+30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;;
+30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;;
+30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;;
+30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;;
+30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;;
+30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;;
+30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;;
+30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;;
+30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;;
+30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;;
+30FB;KATAKANA MIDDLE DOT;Po;0;ON;;;;;N;;;;;
+30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;;
+30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;;
+30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;;
+30FF;KATAKANA DIGRAPH KOTO;Lo;0;L;<vertical> 30B3 30C8;;;;N;;;;;
+3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;;
+3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;;
+3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;;
+3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;;
+3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;;
+310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;;
+310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;;
+310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;;
+310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;;
+310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;;
+310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;;
+3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;;
+3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;;
+3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;;
+3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;;
+3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;;
+3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;;
+3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;;
+3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;;
+3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;;
+3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;;
+311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;;
+311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;;
+311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;;
+311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;;
+311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;;
+311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;;
+3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;;
+3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;;
+3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;;
+3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;;
+3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;;
+3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;;
+3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;;
+3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;;
+3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;;
+3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;;
+312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;;
+312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;;
+312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;;
+312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;;
+3131;HANGUL LETTER KIYEOK;Lo;0;L;<compat> 1100;;;;N;HANGUL LETTER GIYEOG;;;;
+3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L;<compat> 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;;
+3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;;
+3134;HANGUL LETTER NIEUN;Lo;0;L;<compat> 1102;;;;N;;;;;
+3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<compat> 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;;
+3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<compat> 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;;
+3137;HANGUL LETTER TIKEUT;Lo;0;L;<compat> 1103;;;;N;HANGUL LETTER DIGEUD;;;;
+3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L;<compat> 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;;
+3139;HANGUL LETTER RIEUL;Lo;0;L;<compat> 1105;;;;N;HANGUL LETTER LIEUL;;;;
+313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<compat> 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;;
+313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<compat> 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;;
+313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<compat> 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;;
+313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L;<compat> 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;;
+313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<compat> 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;;
+313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<compat> 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;;
+3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<compat> 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;;
+3141;HANGUL LETTER MIEUM;Lo;0;L;<compat> 1106;;;;N;;;;;
+3142;HANGUL LETTER PIEUP;Lo;0;L;<compat> 1107;;;;N;HANGUL LETTER BIEUB;;;;
+3143;HANGUL LETTER SSANGPIEUP;Lo;0;L;<compat> 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;;
+3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L;<compat> 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;;
+3145;HANGUL LETTER SIOS;Lo;0;L;<compat> 1109;;;;N;;;;;
+3146;HANGUL LETTER SSANGSIOS;Lo;0;L;<compat> 110A;;;;N;HANGUL LETTER SSANG SIOS;;;;
+3147;HANGUL LETTER IEUNG;Lo;0;L;<compat> 110B;;;;N;;;;;
+3148;HANGUL LETTER CIEUC;Lo;0;L;<compat> 110C;;;;N;HANGUL LETTER JIEUJ;;;;
+3149;HANGUL LETTER SSANGCIEUC;Lo;0;L;<compat> 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;;
+314A;HANGUL LETTER CHIEUCH;Lo;0;L;<compat> 110E;;;;N;HANGUL LETTER CIEUC;;;;
+314B;HANGUL LETTER KHIEUKH;Lo;0;L;<compat> 110F;;;;N;HANGUL LETTER KIYEOK;;;;
+314C;HANGUL LETTER THIEUTH;Lo;0;L;<compat> 1110;;;;N;HANGUL LETTER TIEUT;;;;
+314D;HANGUL LETTER PHIEUPH;Lo;0;L;<compat> 1111;;;;N;HANGUL LETTER PIEUP;;;;
+314E;HANGUL LETTER HIEUH;Lo;0;L;<compat> 1112;;;;N;;;;;
+314F;HANGUL LETTER A;Lo;0;L;<compat> 1161;;;;N;;;;;
+3150;HANGUL LETTER AE;Lo;0;L;<compat> 1162;;;;N;;;;;
+3151;HANGUL LETTER YA;Lo;0;L;<compat> 1163;;;;N;;;;;
+3152;HANGUL LETTER YAE;Lo;0;L;<compat> 1164;;;;N;;;;;
+3153;HANGUL LETTER EO;Lo;0;L;<compat> 1165;;;;N;;;;;
+3154;HANGUL LETTER E;Lo;0;L;<compat> 1166;;;;N;;;;;
+3155;HANGUL LETTER YEO;Lo;0;L;<compat> 1167;;;;N;;;;;
+3156;HANGUL LETTER YE;Lo;0;L;<compat> 1168;;;;N;;;;;
+3157;HANGUL LETTER O;Lo;0;L;<compat> 1169;;;;N;;;;;
+3158;HANGUL LETTER WA;Lo;0;L;<compat> 116A;;;;N;;;;;
+3159;HANGUL LETTER WAE;Lo;0;L;<compat> 116B;;;;N;;;;;
+315A;HANGUL LETTER OE;Lo;0;L;<compat> 116C;;;;N;;;;;
+315B;HANGUL LETTER YO;Lo;0;L;<compat> 116D;;;;N;;;;;
+315C;HANGUL LETTER U;Lo;0;L;<compat> 116E;;;;N;;;;;
+315D;HANGUL LETTER WEO;Lo;0;L;<compat> 116F;;;;N;;;;;
+315E;HANGUL LETTER WE;Lo;0;L;<compat> 1170;;;;N;;;;;
+315F;HANGUL LETTER WI;Lo;0;L;<compat> 1171;;;;N;;;;;
+3160;HANGUL LETTER YU;Lo;0;L;<compat> 1172;;;;N;;;;;
+3161;HANGUL LETTER EU;Lo;0;L;<compat> 1173;;;;N;;;;;
+3162;HANGUL LETTER YI;Lo;0;L;<compat> 1174;;;;N;;;;;
+3163;HANGUL LETTER I;Lo;0;L;<compat> 1175;;;;N;;;;;
+3164;HANGUL FILLER;Lo;0;L;<compat> 1160;;;;N;HANGUL CAE OM;;;;
+3165;HANGUL LETTER SSANGNIEUN;Lo;0;L;<compat> 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;;
+3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L;<compat> 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;;
+3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L;<compat> 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;;
+3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L;<compat> 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;;
+3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L;<compat> 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;;
+316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L;<compat> 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;;
+316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L;<compat> 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;;
+316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L;<compat> 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;;
+316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L;<compat> 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;;
+316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L;<compat> 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;;
+316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L;<compat> 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;;
+3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L;<compat> 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;;
+3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L;<compat> 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;;
+3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L;<compat> 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;;
+3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L;<compat> 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;;
+3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L;<compat> 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;;
+3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L;<compat> 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;;
+3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L;<compat> 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;;
+3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L;<compat> 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;;
+3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L;<compat> 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;;
+3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L;<compat> 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;;
+317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L;<compat> 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;;
+317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L;<compat> 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;;
+317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L;<compat> 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;;
+317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L;<compat> 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;;
+317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L;<compat> 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;;
+317F;HANGUL LETTER PANSIOS;Lo;0;L;<compat> 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;;
+3180;HANGUL LETTER SSANGIEUNG;Lo;0;L;<compat> 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;;
+3181;HANGUL LETTER YESIEUNG;Lo;0;L;<compat> 114C;;;;N;HANGUL LETTER NGIEUNG;;;;
+3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L;<compat> 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;;
+3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L;<compat> 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;;
+3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L;<compat> 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;;
+3185;HANGUL LETTER SSANGHIEUH;Lo;0;L;<compat> 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;;
+3186;HANGUL LETTER YEORINHIEUH;Lo;0;L;<compat> 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;;
+3187;HANGUL LETTER YO-YA;Lo;0;L;<compat> 1184;;;;N;HANGUL LETTER YOYA;;;;
+3188;HANGUL LETTER YO-YAE;Lo;0;L;<compat> 1185;;;;N;HANGUL LETTER YOYAE;;;;
+3189;HANGUL LETTER YO-I;Lo;0;L;<compat> 1188;;;;N;HANGUL LETTER YOI;;;;
+318A;HANGUL LETTER YU-YEO;Lo;0;L;<compat> 1191;;;;N;HANGUL LETTER YUYEO;;;;
+318B;HANGUL LETTER YU-YE;Lo;0;L;<compat> 1192;;;;N;HANGUL LETTER YUYE;;;;
+318C;HANGUL LETTER YU-I;Lo;0;L;<compat> 1194;;;;N;HANGUL LETTER YUI;;;;
+318D;HANGUL LETTER ARAEA;Lo;0;L;<compat> 119E;;;;N;HANGUL LETTER ALAE A;;;;
+318E;HANGUL LETTER ARAEAE;Lo;0;L;<compat> 11A1;;;;N;HANGUL LETTER ALAE AE;;;;
+3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;;;;
+3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;;;;
+3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L;<super> 4E00;;;1;N;KAERITEN ITI;;;;
+3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L;<super> 4E8C;;;2;N;KAERITEN NI;;;;
+3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L;<super> 4E09;;;3;N;KAERITEN SAN;;;;
+3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L;<super> 56DB;;;4;N;KAERITEN SI;;;;
+3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L;<super> 4E0A;;;;N;KAERITEN ZYOU;;;;
+3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L;<super> 4E2D;;;;N;KAERITEN TYUU;;;;
+3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L;<super> 4E0B;;;;N;KAERITEN GE;;;;
+3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L;<super> 7532;;;;N;KAERITEN KOU;;;;
+319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L;<super> 4E59;;;;N;KAERITEN OTU;;;;
+319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L;<super> 4E19;;;;N;KAERITEN HEI;;;;
+319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L;<super> 4E01;;;;N;KAERITEN TEI;;;;
+319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L;<super> 5929;;;;N;KAERITEN TEN;;;;
+319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L;<super> 5730;;;;N;KAERITEN TI;;;;
+319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L;<super> 4EBA;;;;N;KAERITEN ZIN;;;;
+31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;;
+31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;;
+31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;;
+31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;;
+31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;;
+31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;;
+31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;;
+31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;;
+31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;;
+31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;;
+31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;;
+31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;;
+31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;;
+31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;;
+31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;;
+31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;;
+31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;;
+31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;;
+31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;;
+31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;;
+31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;;
+31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;;
+31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;;
+31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;;
+31C0;CJK STROKE T;So;0;ON;;;;;N;;;;;
+31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;;
+31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;;
+31C3;CJK STROKE BXG;So;0;ON;;;;;N;;;;;
+31C4;CJK STROKE SW;So;0;ON;;;;;N;;;;;
+31C5;CJK STROKE HZZ;So;0;ON;;;;;N;;;;;
+31C6;CJK STROKE HZG;So;0;ON;;;;;N;;;;;
+31C7;CJK STROKE HP;So;0;ON;;;;;N;;;;;
+31C8;CJK STROKE HZWG;So;0;ON;;;;;N;;;;;
+31C9;CJK STROKE SZWG;So;0;ON;;;;;N;;;;;
+31CA;CJK STROKE HZT;So;0;ON;;;;;N;;;;;
+31CB;CJK STROKE HZZP;So;0;ON;;;;;N;;;;;
+31CC;CJK STROKE HPWG;So;0;ON;;;;;N;;;;;
+31CD;CJK STROKE HZW;So;0;ON;;;;;N;;;;;
+31CE;CJK STROKE HZZZ;So;0;ON;;;;;N;;;;;
+31CF;CJK STROKE N;So;0;ON;;;;;N;;;;;
+31D0;CJK STROKE H;So;0;ON;;;;;N;;;;;
+31D1;CJK STROKE S;So;0;ON;;;;;N;;;;;
+31D2;CJK STROKE P;So;0;ON;;;;;N;;;;;
+31D3;CJK STROKE SP;So;0;ON;;;;;N;;;;;
+31D4;CJK STROKE D;So;0;ON;;;;;N;;;;;
+31D5;CJK STROKE HZ;So;0;ON;;;;;N;;;;;
+31D6;CJK STROKE HG;So;0;ON;;;;;N;;;;;
+31D7;CJK STROKE SZ;So;0;ON;;;;;N;;;;;
+31D8;CJK STROKE SWZ;So;0;ON;;;;;N;;;;;
+31D9;CJK STROKE ST;So;0;ON;;;;;N;;;;;
+31DA;CJK STROKE SG;So;0;ON;;;;;N;;;;;
+31DB;CJK STROKE PD;So;0;ON;;;;;N;;;;;
+31DC;CJK STROKE PZ;So;0;ON;;;;;N;;;;;
+31DD;CJK STROKE TN;So;0;ON;;;;;N;;;;;
+31DE;CJK STROKE SZZ;So;0;ON;;;;;N;;;;;
+31DF;CJK STROKE SWG;So;0;ON;;;;;N;;;;;
+31E0;CJK STROKE HXWG;So;0;ON;;;;;N;;;;;
+31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;;
+31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;;
+31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;;
+31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;;
+31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;;
+31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;;
+31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;;
+31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;;
+31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;;
+31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;;
+31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;;
+31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;;
+31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;;
+31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;;
+31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;;
+31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;;
+31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;;
+31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;;
+31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;;
+3200;PARENTHESIZED HANGUL KIYEOK;So;0;L;<compat> 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;;
+3201;PARENTHESIZED HANGUL NIEUN;So;0;L;<compat> 0028 1102 0029;;;;N;;;;;
+3202;PARENTHESIZED HANGUL TIKEUT;So;0;L;<compat> 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;;
+3203;PARENTHESIZED HANGUL RIEUL;So;0;L;<compat> 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;;
+3204;PARENTHESIZED HANGUL MIEUM;So;0;L;<compat> 0028 1106 0029;;;;N;;;;;
+3205;PARENTHESIZED HANGUL PIEUP;So;0;L;<compat> 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;;
+3206;PARENTHESIZED HANGUL SIOS;So;0;L;<compat> 0028 1109 0029;;;;N;;;;;
+3207;PARENTHESIZED HANGUL IEUNG;So;0;L;<compat> 0028 110B 0029;;;;N;;;;;
+3208;PARENTHESIZED HANGUL CIEUC;So;0;L;<compat> 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;;
+3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L;<compat> 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;;
+320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L;<compat> 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;;
+320B;PARENTHESIZED HANGUL THIEUTH;So;0;L;<compat> 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;;
+320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L;<compat> 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;;
+320D;PARENTHESIZED HANGUL HIEUH;So;0;L;<compat> 0028 1112 0029;;;;N;;;;;
+320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L;<compat> 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;;
+320F;PARENTHESIZED HANGUL NIEUN A;So;0;L;<compat> 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;;
+3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L;<compat> 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;;
+3211;PARENTHESIZED HANGUL RIEUL A;So;0;L;<compat> 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;;
+3212;PARENTHESIZED HANGUL MIEUM A;So;0;L;<compat> 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;;
+3213;PARENTHESIZED HANGUL PIEUP A;So;0;L;<compat> 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;;
+3214;PARENTHESIZED HANGUL SIOS A;So;0;L;<compat> 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;;
+3215;PARENTHESIZED HANGUL IEUNG A;So;0;L;<compat> 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;;
+3216;PARENTHESIZED HANGUL CIEUC A;So;0;L;<compat> 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;;
+3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L;<compat> 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;;
+3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L;<compat> 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;;
+3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L;<compat> 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;;
+321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L;<compat> 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;;
+321B;PARENTHESIZED HANGUL HIEUH A;So;0;L;<compat> 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;;
+321C;PARENTHESIZED HANGUL CIEUC U;So;0;L;<compat> 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;;
+321D;PARENTHESIZED KOREAN CHARACTER OJEON;So;0;ON;<compat> 0028 110B 1169 110C 1165 11AB 0029;;;;N;;;;;
+321E;PARENTHESIZED KOREAN CHARACTER O HU;So;0;ON;<compat> 0028 110B 1169 1112 116E 0029;;;;N;;;;;
+3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L;<compat> 0028 4E00 0029;;;1;N;;;;;
+3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L;<compat> 0028 4E8C 0029;;;2;N;;;;;
+3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L;<compat> 0028 4E09 0029;;;3;N;;;;;
+3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L;<compat> 0028 56DB 0029;;;4;N;;;;;
+3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L;<compat> 0028 4E94 0029;;;5;N;;;;;
+3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L;<compat> 0028 516D 0029;;;6;N;;;;;
+3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L;<compat> 0028 4E03 0029;;;7;N;;;;;
+3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L;<compat> 0028 516B 0029;;;8;N;;;;;
+3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L;<compat> 0028 4E5D 0029;;;9;N;;;;;
+3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L;<compat> 0028 5341 0029;;;10;N;;;;;
+322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L;<compat> 0028 6708 0029;;;;N;;;;;
+322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L;<compat> 0028 706B 0029;;;;N;;;;;
+322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L;<compat> 0028 6C34 0029;;;;N;;;;;
+322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L;<compat> 0028 6728 0029;;;;N;;;;;
+322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L;<compat> 0028 91D1 0029;;;;N;;;;;
+322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L;<compat> 0028 571F 0029;;;;N;;;;;
+3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L;<compat> 0028 65E5 0029;;;;N;;;;;
+3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L;<compat> 0028 682A 0029;;;;N;;;;;
+3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L;<compat> 0028 6709 0029;;;;N;;;;;
+3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L;<compat> 0028 793E 0029;;;;N;;;;;
+3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L;<compat> 0028 540D 0029;;;;N;;;;;
+3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L;<compat> 0028 7279 0029;;;;N;;;;;
+3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L;<compat> 0028 8CA1 0029;;;;N;;;;;
+3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L;<compat> 0028 795D 0029;;;;N;;;;;
+3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L;<compat> 0028 52B4 0029;;;;N;;;;;
+3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L;<compat> 0028 4EE3 0029;;;;N;;;;;
+323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L;<compat> 0028 547C 0029;;;;N;;;;;
+323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L;<compat> 0028 5B66 0029;;;;N;;;;;
+323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L;<compat> 0028 76E3 0029;;;;N;;;;;
+323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L;<compat> 0028 4F01 0029;;;;N;;;;;
+323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L;<compat> 0028 8CC7 0029;;;;N;;;;;
+323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L;<compat> 0028 5354 0029;;;;N;;;;;
+3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L;<compat> 0028 796D 0029;;;;N;;;;;
+3241;PARENTHESIZED IDEOGRAPH REST;So;0;L;<compat> 0028 4F11 0029;;;;N;;;;;
+3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L;<compat> 0028 81EA 0029;;;;N;;;;;
+3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L;<compat> 0028 81F3 0029;;;;N;;;;;
+3244;CIRCLED IDEOGRAPH QUESTION;So;0;L;<circle> 554F;;;;N;;;;;
+3245;CIRCLED IDEOGRAPH KINDERGARTEN;So;0;L;<circle> 5E7C;;;;N;;;;;
+3246;CIRCLED IDEOGRAPH SCHOOL;So;0;L;<circle> 6587;;;;N;;;;;
+3247;CIRCLED IDEOGRAPH KOTO;So;0;L;<circle> 7B8F;;;;N;;;;;
+3248;CIRCLED NUMBER TEN ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+3249;CIRCLED NUMBER TWENTY ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+324A;CIRCLED NUMBER THIRTY ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+324B;CIRCLED NUMBER FORTY ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+324C;CIRCLED NUMBER FIFTY ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+324D;CIRCLED NUMBER SIXTY ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+324E;CIRCLED NUMBER SEVENTY ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+324F;CIRCLED NUMBER EIGHTY ON BLACK SQUARE;So;0;L;;;;;N;;;;;
+3250;PARTNERSHIP SIGN;So;0;ON;<square> 0050 0054 0045;;;;N;;;;;
+3251;CIRCLED NUMBER TWENTY ONE;No;0;ON;<circle> 0032 0031;;;21;N;;;;;
+3252;CIRCLED NUMBER TWENTY TWO;No;0;ON;<circle> 0032 0032;;;22;N;;;;;
+3253;CIRCLED NUMBER TWENTY THREE;No;0;ON;<circle> 0032 0033;;;23;N;;;;;
+3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON;<circle> 0032 0034;;;24;N;;;;;
+3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON;<circle> 0032 0035;;;25;N;;;;;
+3256;CIRCLED NUMBER TWENTY SIX;No;0;ON;<circle> 0032 0036;;;26;N;;;;;
+3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON;<circle> 0032 0037;;;27;N;;;;;
+3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON;<circle> 0032 0038;;;28;N;;;;;
+3259;CIRCLED NUMBER TWENTY NINE;No;0;ON;<circle> 0032 0039;;;29;N;;;;;
+325A;CIRCLED NUMBER THIRTY;No;0;ON;<circle> 0033 0030;;;30;N;;;;;
+325B;CIRCLED NUMBER THIRTY ONE;No;0;ON;<circle> 0033 0031;;;31;N;;;;;
+325C;CIRCLED NUMBER THIRTY TWO;No;0;ON;<circle> 0033 0032;;;32;N;;;;;
+325D;CIRCLED NUMBER THIRTY THREE;No;0;ON;<circle> 0033 0033;;;33;N;;;;;
+325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON;<circle> 0033 0034;;;34;N;;;;;
+325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON;<circle> 0033 0035;;;35;N;;;;;
+3260;CIRCLED HANGUL KIYEOK;So;0;L;<circle> 1100;;;;N;CIRCLED HANGUL GIYEOG;;;;
+3261;CIRCLED HANGUL NIEUN;So;0;L;<circle> 1102;;;;N;;;;;
+3262;CIRCLED HANGUL TIKEUT;So;0;L;<circle> 1103;;;;N;CIRCLED HANGUL DIGEUD;;;;
+3263;CIRCLED HANGUL RIEUL;So;0;L;<circle> 1105;;;;N;CIRCLED HANGUL LIEUL;;;;
+3264;CIRCLED HANGUL MIEUM;So;0;L;<circle> 1106;;;;N;;;;;
+3265;CIRCLED HANGUL PIEUP;So;0;L;<circle> 1107;;;;N;CIRCLED HANGUL BIEUB;;;;
+3266;CIRCLED HANGUL SIOS;So;0;L;<circle> 1109;;;;N;;;;;
+3267;CIRCLED HANGUL IEUNG;So;0;L;<circle> 110B;;;;N;;;;;
+3268;CIRCLED HANGUL CIEUC;So;0;L;<circle> 110C;;;;N;CIRCLED HANGUL JIEUJ;;;;
+3269;CIRCLED HANGUL CHIEUCH;So;0;L;<circle> 110E;;;;N;CIRCLED HANGUL CIEUC;;;;
+326A;CIRCLED HANGUL KHIEUKH;So;0;L;<circle> 110F;;;;N;CIRCLED HANGUL KIYEOK;;;;
+326B;CIRCLED HANGUL THIEUTH;So;0;L;<circle> 1110;;;;N;CIRCLED HANGUL TIEUT;;;;
+326C;CIRCLED HANGUL PHIEUPH;So;0;L;<circle> 1111;;;;N;CIRCLED HANGUL PIEUP;;;;
+326D;CIRCLED HANGUL HIEUH;So;0;L;<circle> 1112;;;;N;;;;;
+326E;CIRCLED HANGUL KIYEOK A;So;0;L;<circle> 1100 1161;;;;N;CIRCLED HANGUL GA;;;;
+326F;CIRCLED HANGUL NIEUN A;So;0;L;<circle> 1102 1161;;;;N;CIRCLED HANGUL NA;;;;
+3270;CIRCLED HANGUL TIKEUT A;So;0;L;<circle> 1103 1161;;;;N;CIRCLED HANGUL DA;;;;
+3271;CIRCLED HANGUL RIEUL A;So;0;L;<circle> 1105 1161;;;;N;CIRCLED HANGUL LA;;;;
+3272;CIRCLED HANGUL MIEUM A;So;0;L;<circle> 1106 1161;;;;N;CIRCLED HANGUL MA;;;;
+3273;CIRCLED HANGUL PIEUP A;So;0;L;<circle> 1107 1161;;;;N;CIRCLED HANGUL BA;;;;
+3274;CIRCLED HANGUL SIOS A;So;0;L;<circle> 1109 1161;;;;N;CIRCLED HANGUL SA;;;;
+3275;CIRCLED HANGUL IEUNG A;So;0;L;<circle> 110B 1161;;;;N;CIRCLED HANGUL A;;;;
+3276;CIRCLED HANGUL CIEUC A;So;0;L;<circle> 110C 1161;;;;N;CIRCLED HANGUL JA;;;;
+3277;CIRCLED HANGUL CHIEUCH A;So;0;L;<circle> 110E 1161;;;;N;CIRCLED HANGUL CA;;;;
+3278;CIRCLED HANGUL KHIEUKH A;So;0;L;<circle> 110F 1161;;;;N;CIRCLED HANGUL KA;;;;
+3279;CIRCLED HANGUL THIEUTH A;So;0;L;<circle> 1110 1161;;;;N;CIRCLED HANGUL TA;;;;
+327A;CIRCLED HANGUL PHIEUPH A;So;0;L;<circle> 1111 1161;;;;N;CIRCLED HANGUL PA;;;;
+327B;CIRCLED HANGUL HIEUH A;So;0;L;<circle> 1112 1161;;;;N;CIRCLED HANGUL HA;;;;
+327C;CIRCLED KOREAN CHARACTER CHAMKO;So;0;ON;<circle> 110E 1161 11B7 1100 1169;;;;N;;;;;
+327D;CIRCLED KOREAN CHARACTER JUEUI;So;0;ON;<circle> 110C 116E 110B 1174;;;;N;;;;;
+327E;CIRCLED HANGUL IEUNG U;So;0;ON;<circle> 110B 116E;;;;N;;;;;
+327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;;
+3280;CIRCLED IDEOGRAPH ONE;No;0;L;<circle> 4E00;;;1;N;;;;;
+3281;CIRCLED IDEOGRAPH TWO;No;0;L;<circle> 4E8C;;;2;N;;;;;
+3282;CIRCLED IDEOGRAPH THREE;No;0;L;<circle> 4E09;;;3;N;;;;;
+3283;CIRCLED IDEOGRAPH FOUR;No;0;L;<circle> 56DB;;;4;N;;;;;
+3284;CIRCLED IDEOGRAPH FIVE;No;0;L;<circle> 4E94;;;5;N;;;;;
+3285;CIRCLED IDEOGRAPH SIX;No;0;L;<circle> 516D;;;6;N;;;;;
+3286;CIRCLED IDEOGRAPH SEVEN;No;0;L;<circle> 4E03;;;7;N;;;;;
+3287;CIRCLED IDEOGRAPH EIGHT;No;0;L;<circle> 516B;;;8;N;;;;;
+3288;CIRCLED IDEOGRAPH NINE;No;0;L;<circle> 4E5D;;;9;N;;;;;
+3289;CIRCLED IDEOGRAPH TEN;No;0;L;<circle> 5341;;;10;N;;;;;
+328A;CIRCLED IDEOGRAPH MOON;So;0;L;<circle> 6708;;;;N;;;;;
+328B;CIRCLED IDEOGRAPH FIRE;So;0;L;<circle> 706B;;;;N;;;;;
+328C;CIRCLED IDEOGRAPH WATER;So;0;L;<circle> 6C34;;;;N;;;;;
+328D;CIRCLED IDEOGRAPH WOOD;So;0;L;<circle> 6728;;;;N;;;;;
+328E;CIRCLED IDEOGRAPH METAL;So;0;L;<circle> 91D1;;;;N;;;;;
+328F;CIRCLED IDEOGRAPH EARTH;So;0;L;<circle> 571F;;;;N;;;;;
+3290;CIRCLED IDEOGRAPH SUN;So;0;L;<circle> 65E5;;;;N;;;;;
+3291;CIRCLED IDEOGRAPH STOCK;So;0;L;<circle> 682A;;;;N;;;;;
+3292;CIRCLED IDEOGRAPH HAVE;So;0;L;<circle> 6709;;;;N;;;;;
+3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L;<circle> 793E;;;;N;;;;;
+3294;CIRCLED IDEOGRAPH NAME;So;0;L;<circle> 540D;;;;N;;;;;
+3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L;<circle> 7279;;;;N;;;;;
+3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L;<circle> 8CA1;;;;N;;;;;
+3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L;<circle> 795D;;;;N;;;;;
+3298;CIRCLED IDEOGRAPH LABOR;So;0;L;<circle> 52B4;;;;N;;;;;
+3299;CIRCLED IDEOGRAPH SECRET;So;0;L;<circle> 79D8;;;;N;;;;;
+329A;CIRCLED IDEOGRAPH MALE;So;0;L;<circle> 7537;;;;N;;;;;
+329B;CIRCLED IDEOGRAPH FEMALE;So;0;L;<circle> 5973;;;;N;;;;;
+329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L;<circle> 9069;;;;N;;;;;
+329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L;<circle> 512A;;;;N;;;;;
+329E;CIRCLED IDEOGRAPH PRINT;So;0;L;<circle> 5370;;;;N;;;;;
+329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L;<circle> 6CE8;;;;N;;;;;
+32A0;CIRCLED IDEOGRAPH ITEM;So;0;L;<circle> 9805;;;;N;;;;;
+32A1;CIRCLED IDEOGRAPH REST;So;0;L;<circle> 4F11;;;;N;;;;;
+32A2;CIRCLED IDEOGRAPH COPY;So;0;L;<circle> 5199;;;;N;;;;;
+32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L;<circle> 6B63;;;;N;;;;;
+32A4;CIRCLED IDEOGRAPH HIGH;So;0;L;<circle> 4E0A;;;;N;;;;;
+32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L;<circle> 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;;
+32A6;CIRCLED IDEOGRAPH LOW;So;0;L;<circle> 4E0B;;;;N;;;;;
+32A7;CIRCLED IDEOGRAPH LEFT;So;0;L;<circle> 5DE6;;;;N;;;;;
+32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L;<circle> 53F3;;;;N;;;;;
+32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L;<circle> 533B;;;;N;;;;;
+32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L;<circle> 5B97;;;;N;;;;;
+32AB;CIRCLED IDEOGRAPH STUDY;So;0;L;<circle> 5B66;;;;N;;;;;
+32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L;<circle> 76E3;;;;N;;;;;
+32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L;<circle> 4F01;;;;N;;;;;
+32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L;<circle> 8CC7;;;;N;;;;;
+32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L;<circle> 5354;;;;N;;;;;
+32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L;<circle> 591C;;;;N;;;;;
+32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON;<circle> 0033 0036;;;36;N;;;;;
+32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON;<circle> 0033 0037;;;37;N;;;;;
+32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON;<circle> 0033 0038;;;38;N;;;;;
+32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON;<circle> 0033 0039;;;39;N;;;;;
+32B5;CIRCLED NUMBER FORTY;No;0;ON;<circle> 0034 0030;;;40;N;;;;;
+32B6;CIRCLED NUMBER FORTY ONE;No;0;ON;<circle> 0034 0031;;;41;N;;;;;
+32B7;CIRCLED NUMBER FORTY TWO;No;0;ON;<circle> 0034 0032;;;42;N;;;;;
+32B8;CIRCLED NUMBER FORTY THREE;No;0;ON;<circle> 0034 0033;;;43;N;;;;;
+32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON;<circle> 0034 0034;;;44;N;;;;;
+32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON;<circle> 0034 0035;;;45;N;;;;;
+32BB;CIRCLED NUMBER FORTY SIX;No;0;ON;<circle> 0034 0036;;;46;N;;;;;
+32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON;<circle> 0034 0037;;;47;N;;;;;
+32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON;<circle> 0034 0038;;;48;N;;;;;
+32BE;CIRCLED NUMBER FORTY NINE;No;0;ON;<circle> 0034 0039;;;49;N;;;;;
+32BF;CIRCLED NUMBER FIFTY;No;0;ON;<circle> 0035 0030;;;50;N;;;;;
+32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L;<compat> 0031 6708;;;;N;;;;;
+32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L;<compat> 0032 6708;;;;N;;;;;
+32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L;<compat> 0033 6708;;;;N;;;;;
+32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L;<compat> 0034 6708;;;;N;;;;;
+32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L;<compat> 0035 6708;;;;N;;;;;
+32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L;<compat> 0036 6708;;;;N;;;;;
+32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L;<compat> 0037 6708;;;;N;;;;;
+32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L;<compat> 0038 6708;;;;N;;;;;
+32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L;<compat> 0039 6708;;;;N;;;;;
+32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L;<compat> 0031 0030 6708;;;;N;;;;;
+32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L;<compat> 0031 0031 6708;;;;N;;;;;
+32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L;<compat> 0031 0032 6708;;;;N;;;;;
+32CC;SQUARE HG;So;0;ON;<square> 0048 0067;;;;N;;;;;
+32CD;SQUARE ERG;So;0;ON;<square> 0065 0072 0067;;;;N;;;;;
+32CE;SQUARE EV;So;0;ON;<square> 0065 0056;;;;N;;;;;
+32CF;LIMITED LIABILITY SIGN;So;0;ON;<square> 004C 0054 0044;;;;N;;;;;
+32D0;CIRCLED KATAKANA A;So;0;L;<circle> 30A2;;;;N;;;;;
+32D1;CIRCLED KATAKANA I;So;0;L;<circle> 30A4;;;;N;;;;;
+32D2;CIRCLED KATAKANA U;So;0;L;<circle> 30A6;;;;N;;;;;
+32D3;CIRCLED KATAKANA E;So;0;L;<circle> 30A8;;;;N;;;;;
+32D4;CIRCLED KATAKANA O;So;0;L;<circle> 30AA;;;;N;;;;;
+32D5;CIRCLED KATAKANA KA;So;0;L;<circle> 30AB;;;;N;;;;;
+32D6;CIRCLED KATAKANA KI;So;0;L;<circle> 30AD;;;;N;;;;;
+32D7;CIRCLED KATAKANA KU;So;0;L;<circle> 30AF;;;;N;;;;;
+32D8;CIRCLED KATAKANA KE;So;0;L;<circle> 30B1;;;;N;;;;;
+32D9;CIRCLED KATAKANA KO;So;0;L;<circle> 30B3;;;;N;;;;;
+32DA;CIRCLED KATAKANA SA;So;0;L;<circle> 30B5;;;;N;;;;;
+32DB;CIRCLED KATAKANA SI;So;0;L;<circle> 30B7;;;;N;;;;;
+32DC;CIRCLED KATAKANA SU;So;0;L;<circle> 30B9;;;;N;;;;;
+32DD;CIRCLED KATAKANA SE;So;0;L;<circle> 30BB;;;;N;;;;;
+32DE;CIRCLED KATAKANA SO;So;0;L;<circle> 30BD;;;;N;;;;;
+32DF;CIRCLED KATAKANA TA;So;0;L;<circle> 30BF;;;;N;;;;;
+32E0;CIRCLED KATAKANA TI;So;0;L;<circle> 30C1;;;;N;;;;;
+32E1;CIRCLED KATAKANA TU;So;0;L;<circle> 30C4;;;;N;;;;;
+32E2;CIRCLED KATAKANA TE;So;0;L;<circle> 30C6;;;;N;;;;;
+32E3;CIRCLED KATAKANA TO;So;0;L;<circle> 30C8;;;;N;;;;;
+32E4;CIRCLED KATAKANA NA;So;0;L;<circle> 30CA;;;;N;;;;;
+32E5;CIRCLED KATAKANA NI;So;0;L;<circle> 30CB;;;;N;;;;;
+32E6;CIRCLED KATAKANA NU;So;0;L;<circle> 30CC;;;;N;;;;;
+32E7;CIRCLED KATAKANA NE;So;0;L;<circle> 30CD;;;;N;;;;;
+32E8;CIRCLED KATAKANA NO;So;0;L;<circle> 30CE;;;;N;;;;;
+32E9;CIRCLED KATAKANA HA;So;0;L;<circle> 30CF;;;;N;;;;;
+32EA;CIRCLED KATAKANA HI;So;0;L;<circle> 30D2;;;;N;;;;;
+32EB;CIRCLED KATAKANA HU;So;0;L;<circle> 30D5;;;;N;;;;;
+32EC;CIRCLED KATAKANA HE;So;0;L;<circle> 30D8;;;;N;;;;;
+32ED;CIRCLED KATAKANA HO;So;0;L;<circle> 30DB;;;;N;;;;;
+32EE;CIRCLED KATAKANA MA;So;0;L;<circle> 30DE;;;;N;;;;;
+32EF;CIRCLED KATAKANA MI;So;0;L;<circle> 30DF;;;;N;;;;;
+32F0;CIRCLED KATAKANA MU;So;0;L;<circle> 30E0;;;;N;;;;;
+32F1;CIRCLED KATAKANA ME;So;0;L;<circle> 30E1;;;;N;;;;;
+32F2;CIRCLED KATAKANA MO;So;0;L;<circle> 30E2;;;;N;;;;;
+32F3;CIRCLED KATAKANA YA;So;0;L;<circle> 30E4;;;;N;;;;;
+32F4;CIRCLED KATAKANA YU;So;0;L;<circle> 30E6;;;;N;;;;;
+32F5;CIRCLED KATAKANA YO;So;0;L;<circle> 30E8;;;;N;;;;;
+32F6;CIRCLED KATAKANA RA;So;0;L;<circle> 30E9;;;;N;;;;;
+32F7;CIRCLED KATAKANA RI;So;0;L;<circle> 30EA;;;;N;;;;;
+32F8;CIRCLED KATAKANA RU;So;0;L;<circle> 30EB;;;;N;;;;;
+32F9;CIRCLED KATAKANA RE;So;0;L;<circle> 30EC;;;;N;;;;;
+32FA;CIRCLED KATAKANA RO;So;0;L;<circle> 30ED;;;;N;;;;;
+32FB;CIRCLED KATAKANA WA;So;0;L;<circle> 30EF;;;;N;;;;;
+32FC;CIRCLED KATAKANA WI;So;0;L;<circle> 30F0;;;;N;;;;;
+32FD;CIRCLED KATAKANA WE;So;0;L;<circle> 30F1;;;;N;;;;;
+32FE;CIRCLED KATAKANA WO;So;0;L;<circle> 30F2;;;;N;;;;;
+3300;SQUARE APAATO;So;0;L;<square> 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;;
+3301;SQUARE ARUHUA;So;0;L;<square> 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;;
+3302;SQUARE ANPEA;So;0;L;<square> 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;;
+3303;SQUARE AARU;So;0;L;<square> 30A2 30FC 30EB;;;;N;SQUARED AARU;;;;
+3304;SQUARE ININGU;So;0;L;<square> 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;;
+3305;SQUARE INTI;So;0;L;<square> 30A4 30F3 30C1;;;;N;SQUARED INTI;;;;
+3306;SQUARE UON;So;0;L;<square> 30A6 30A9 30F3;;;;N;SQUARED UON;;;;
+3307;SQUARE ESUKUUDO;So;0;L;<square> 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;;
+3308;SQUARE EEKAA;So;0;L;<square> 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;;
+3309;SQUARE ONSU;So;0;L;<square> 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;;
+330A;SQUARE OOMU;So;0;L;<square> 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;;
+330B;SQUARE KAIRI;So;0;L;<square> 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;;
+330C;SQUARE KARATTO;So;0;L;<square> 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;;
+330D;SQUARE KARORII;So;0;L;<square> 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;;
+330E;SQUARE GARON;So;0;L;<square> 30AC 30ED 30F3;;;;N;SQUARED GARON;;;;
+330F;SQUARE GANMA;So;0;L;<square> 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;;
+3310;SQUARE GIGA;So;0;L;<square> 30AE 30AC;;;;N;SQUARED GIGA;;;;
+3311;SQUARE GINII;So;0;L;<square> 30AE 30CB 30FC;;;;N;SQUARED GINII;;;;
+3312;SQUARE KYURII;So;0;L;<square> 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;;
+3313;SQUARE GIRUDAA;So;0;L;<square> 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;;
+3314;SQUARE KIRO;So;0;L;<square> 30AD 30ED;;;;N;SQUARED KIRO;;;;
+3315;SQUARE KIROGURAMU;So;0;L;<square> 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;;
+3316;SQUARE KIROMEETORU;So;0;L;<square> 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;;
+3317;SQUARE KIROWATTO;So;0;L;<square> 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;;
+3318;SQUARE GURAMU;So;0;L;<square> 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;;
+3319;SQUARE GURAMUTON;So;0;L;<square> 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;;
+331A;SQUARE KURUZEIRO;So;0;L;<square> 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;;
+331B;SQUARE KUROONE;So;0;L;<square> 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;;
+331C;SQUARE KEESU;So;0;L;<square> 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;;
+331D;SQUARE KORUNA;So;0;L;<square> 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;;
+331E;SQUARE KOOPO;So;0;L;<square> 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;;
+331F;SQUARE SAIKURU;So;0;L;<square> 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;;
+3320;SQUARE SANTIIMU;So;0;L;<square> 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;;
+3321;SQUARE SIRINGU;So;0;L;<square> 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;;
+3322;SQUARE SENTI;So;0;L;<square> 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;;
+3323;SQUARE SENTO;So;0;L;<square> 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;;
+3324;SQUARE DAASU;So;0;L;<square> 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;;
+3325;SQUARE DESI;So;0;L;<square> 30C7 30B7;;;;N;SQUARED DESI;;;;
+3326;SQUARE DORU;So;0;L;<square> 30C9 30EB;;;;N;SQUARED DORU;;;;
+3327;SQUARE TON;So;0;L;<square> 30C8 30F3;;;;N;SQUARED TON;;;;
+3328;SQUARE NANO;So;0;L;<square> 30CA 30CE;;;;N;SQUARED NANO;;;;
+3329;SQUARE NOTTO;So;0;L;<square> 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;;
+332A;SQUARE HAITU;So;0;L;<square> 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;;
+332B;SQUARE PAASENTO;So;0;L;<square> 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;;
+332C;SQUARE PAATU;So;0;L;<square> 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;;
+332D;SQUARE BAARERU;So;0;L;<square> 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;;
+332E;SQUARE PIASUTORU;So;0;L;<square> 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;;
+332F;SQUARE PIKURU;So;0;L;<square> 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;;
+3330;SQUARE PIKO;So;0;L;<square> 30D4 30B3;;;;N;SQUARED PIKO;;;;
+3331;SQUARE BIRU;So;0;L;<square> 30D3 30EB;;;;N;SQUARED BIRU;;;;
+3332;SQUARE HUARADDO;So;0;L;<square> 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;;
+3333;SQUARE HUIITO;So;0;L;<square> 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;;
+3334;SQUARE BUSSYERU;So;0;L;<square> 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;;
+3335;SQUARE HURAN;So;0;L;<square> 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;;
+3336;SQUARE HEKUTAARU;So;0;L;<square> 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;;
+3337;SQUARE PESO;So;0;L;<square> 30DA 30BD;;;;N;SQUARED PESO;;;;
+3338;SQUARE PENIHI;So;0;L;<square> 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;;
+3339;SQUARE HERUTU;So;0;L;<square> 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;;
+333A;SQUARE PENSU;So;0;L;<square> 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;;
+333B;SQUARE PEEZI;So;0;L;<square> 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;;
+333C;SQUARE BEETA;So;0;L;<square> 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;;
+333D;SQUARE POINTO;So;0;L;<square> 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;;
+333E;SQUARE BORUTO;So;0;L;<square> 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;;
+333F;SQUARE HON;So;0;L;<square> 30DB 30F3;;;;N;SQUARED HON;;;;
+3340;SQUARE PONDO;So;0;L;<square> 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;;
+3341;SQUARE HOORU;So;0;L;<square> 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;;
+3342;SQUARE HOON;So;0;L;<square> 30DB 30FC 30F3;;;;N;SQUARED HOON;;;;
+3343;SQUARE MAIKURO;So;0;L;<square> 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;;
+3344;SQUARE MAIRU;So;0;L;<square> 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;;
+3345;SQUARE MAHHA;So;0;L;<square> 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;;
+3346;SQUARE MARUKU;So;0;L;<square> 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;;
+3347;SQUARE MANSYON;So;0;L;<square> 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;;
+3348;SQUARE MIKURON;So;0;L;<square> 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;;
+3349;SQUARE MIRI;So;0;L;<square> 30DF 30EA;;;;N;SQUARED MIRI;;;;
+334A;SQUARE MIRIBAARU;So;0;L;<square> 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;;
+334B;SQUARE MEGA;So;0;L;<square> 30E1 30AC;;;;N;SQUARED MEGA;;;;
+334C;SQUARE MEGATON;So;0;L;<square> 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;;
+334D;SQUARE MEETORU;So;0;L;<square> 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;;
+334E;SQUARE YAADO;So;0;L;<square> 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;;
+334F;SQUARE YAARU;So;0;L;<square> 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;;
+3350;SQUARE YUAN;So;0;L;<square> 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;;
+3351;SQUARE RITTORU;So;0;L;<square> 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;;
+3352;SQUARE RIRA;So;0;L;<square> 30EA 30E9;;;;N;SQUARED RIRA;;;;
+3353;SQUARE RUPII;So;0;L;<square> 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;;
+3354;SQUARE RUUBURU;So;0;L;<square> 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;;
+3355;SQUARE REMU;So;0;L;<square> 30EC 30E0;;;;N;SQUARED REMU;;;;
+3356;SQUARE RENTOGEN;So;0;L;<square> 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;;
+3357;SQUARE WATTO;So;0;L;<square> 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;;
+3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L;<compat> 0030 70B9;;;;N;;;;;
+3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L;<compat> 0031 70B9;;;;N;;;;;
+335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L;<compat> 0032 70B9;;;;N;;;;;
+335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L;<compat> 0033 70B9;;;;N;;;;;
+335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L;<compat> 0034 70B9;;;;N;;;;;
+335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L;<compat> 0035 70B9;;;;N;;;;;
+335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L;<compat> 0036 70B9;;;;N;;;;;
+335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L;<compat> 0037 70B9;;;;N;;;;;
+3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L;<compat> 0038 70B9;;;;N;;;;;
+3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L;<compat> 0039 70B9;;;;N;;;;;
+3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L;<compat> 0031 0030 70B9;;;;N;;;;;
+3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L;<compat> 0031 0031 70B9;;;;N;;;;;
+3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L;<compat> 0031 0032 70B9;;;;N;;;;;
+3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L;<compat> 0031 0033 70B9;;;;N;;;;;
+3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L;<compat> 0031 0034 70B9;;;;N;;;;;
+3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L;<compat> 0031 0035 70B9;;;;N;;;;;
+3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L;<compat> 0031 0036 70B9;;;;N;;;;;
+3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L;<compat> 0031 0037 70B9;;;;N;;;;;
+336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L;<compat> 0031 0038 70B9;;;;N;;;;;
+336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L;<compat> 0031 0039 70B9;;;;N;;;;;
+336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L;<compat> 0032 0030 70B9;;;;N;;;;;
+336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L;<compat> 0032 0031 70B9;;;;N;;;;;
+336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L;<compat> 0032 0032 70B9;;;;N;;;;;
+336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L;<compat> 0032 0033 70B9;;;;N;;;;;
+3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L;<compat> 0032 0034 70B9;;;;N;;;;;
+3371;SQUARE HPA;So;0;L;<square> 0068 0050 0061;;;;N;;;;;
+3372;SQUARE DA;So;0;L;<square> 0064 0061;;;;N;;;;;
+3373;SQUARE AU;So;0;L;<square> 0041 0055;;;;N;;;;;
+3374;SQUARE BAR;So;0;L;<square> 0062 0061 0072;;;;N;;;;;
+3375;SQUARE OV;So;0;L;<square> 006F 0056;;;;N;;;;;
+3376;SQUARE PC;So;0;L;<square> 0070 0063;;;;N;;;;;
+3377;SQUARE DM;So;0;ON;<square> 0064 006D;;;;N;;;;;
+3378;SQUARE DM SQUARED;So;0;ON;<square> 0064 006D 00B2;;;;N;;;;;
+3379;SQUARE DM CUBED;So;0;ON;<square> 0064 006D 00B3;;;;N;;;;;
+337A;SQUARE IU;So;0;ON;<square> 0049 0055;;;;N;;;;;
+337B;SQUARE ERA NAME HEISEI;So;0;L;<square> 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;;
+337C;SQUARE ERA NAME SYOUWA;So;0;L;<square> 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;;
+337D;SQUARE ERA NAME TAISYOU;So;0;L;<square> 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;;
+337E;SQUARE ERA NAME MEIZI;So;0;L;<square> 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;;
+337F;SQUARE CORPORATION;So;0;L;<square> 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;;
+3380;SQUARE PA AMPS;So;0;L;<square> 0070 0041;;;;N;SQUARED PA AMPS;;;;
+3381;SQUARE NA;So;0;L;<square> 006E 0041;;;;N;SQUARED NA;;;;
+3382;SQUARE MU A;So;0;L;<square> 03BC 0041;;;;N;SQUARED MU A;;;;
+3383;SQUARE MA;So;0;L;<square> 006D 0041;;;;N;SQUARED MA;;;;
+3384;SQUARE KA;So;0;L;<square> 006B 0041;;;;N;SQUARED KA;;;;
+3385;SQUARE KB;So;0;L;<square> 004B 0042;;;;N;SQUARED KB;;;;
+3386;SQUARE MB;So;0;L;<square> 004D 0042;;;;N;SQUARED MB;;;;
+3387;SQUARE GB;So;0;L;<square> 0047 0042;;;;N;SQUARED GB;;;;
+3388;SQUARE CAL;So;0;L;<square> 0063 0061 006C;;;;N;SQUARED CAL;;;;
+3389;SQUARE KCAL;So;0;L;<square> 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;;
+338A;SQUARE PF;So;0;L;<square> 0070 0046;;;;N;SQUARED PF;;;;
+338B;SQUARE NF;So;0;L;<square> 006E 0046;;;;N;SQUARED NF;;;;
+338C;SQUARE MU F;So;0;L;<square> 03BC 0046;;;;N;SQUARED MU F;;;;
+338D;SQUARE MU G;So;0;L;<square> 03BC 0067;;;;N;SQUARED MU G;;;;
+338E;SQUARE MG;So;0;L;<square> 006D 0067;;;;N;SQUARED MG;;;;
+338F;SQUARE KG;So;0;L;<square> 006B 0067;;;;N;SQUARED KG;;;;
+3390;SQUARE HZ;So;0;L;<square> 0048 007A;;;;N;SQUARED HZ;;;;
+3391;SQUARE KHZ;So;0;L;<square> 006B 0048 007A;;;;N;SQUARED KHZ;;;;
+3392;SQUARE MHZ;So;0;L;<square> 004D 0048 007A;;;;N;SQUARED MHZ;;;;
+3393;SQUARE GHZ;So;0;L;<square> 0047 0048 007A;;;;N;SQUARED GHZ;;;;
+3394;SQUARE THZ;So;0;L;<square> 0054 0048 007A;;;;N;SQUARED THZ;;;;
+3395;SQUARE MU L;So;0;L;<square> 03BC 2113;;;;N;SQUARED MU L;;;;
+3396;SQUARE ML;So;0;L;<square> 006D 2113;;;;N;SQUARED ML;;;;
+3397;SQUARE DL;So;0;L;<square> 0064 2113;;;;N;SQUARED DL;;;;
+3398;SQUARE KL;So;0;L;<square> 006B 2113;;;;N;SQUARED KL;;;;
+3399;SQUARE FM;So;0;L;<square> 0066 006D;;;;N;SQUARED FM;;;;
+339A;SQUARE NM;So;0;L;<square> 006E 006D;;;;N;SQUARED NM;;;;
+339B;SQUARE MU M;So;0;L;<square> 03BC 006D;;;;N;SQUARED MU M;;;;
+339C;SQUARE MM;So;0;L;<square> 006D 006D;;;;N;SQUARED MM;;;;
+339D;SQUARE CM;So;0;L;<square> 0063 006D;;;;N;SQUARED CM;;;;
+339E;SQUARE KM;So;0;L;<square> 006B 006D;;;;N;SQUARED KM;;;;
+339F;SQUARE MM SQUARED;So;0;L;<square> 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;;
+33A0;SQUARE CM SQUARED;So;0;L;<square> 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;;
+33A1;SQUARE M SQUARED;So;0;L;<square> 006D 00B2;;;;N;SQUARED M SQUARED;;;;
+33A2;SQUARE KM SQUARED;So;0;L;<square> 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;;
+33A3;SQUARE MM CUBED;So;0;L;<square> 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;;
+33A4;SQUARE CM CUBED;So;0;L;<square> 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;;
+33A5;SQUARE M CUBED;So;0;L;<square> 006D 00B3;;;;N;SQUARED M CUBED;;;;
+33A6;SQUARE KM CUBED;So;0;L;<square> 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;;
+33A7;SQUARE M OVER S;So;0;L;<square> 006D 2215 0073;;;;N;SQUARED M OVER S;;;;
+33A8;SQUARE M OVER S SQUARED;So;0;L;<square> 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;;
+33A9;SQUARE PA;So;0;L;<square> 0050 0061;;;;N;SQUARED PA;;;;
+33AA;SQUARE KPA;So;0;L;<square> 006B 0050 0061;;;;N;SQUARED KPA;;;;
+33AB;SQUARE MPA;So;0;L;<square> 004D 0050 0061;;;;N;SQUARED MPA;;;;
+33AC;SQUARE GPA;So;0;L;<square> 0047 0050 0061;;;;N;SQUARED GPA;;;;
+33AD;SQUARE RAD;So;0;L;<square> 0072 0061 0064;;;;N;SQUARED RAD;;;;
+33AE;SQUARE RAD OVER S;So;0;L;<square> 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;;
+33AF;SQUARE RAD OVER S SQUARED;So;0;L;<square> 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;;
+33B0;SQUARE PS;So;0;L;<square> 0070 0073;;;;N;SQUARED PS;;;;
+33B1;SQUARE NS;So;0;L;<square> 006E 0073;;;;N;SQUARED NS;;;;
+33B2;SQUARE MU S;So;0;L;<square> 03BC 0073;;;;N;SQUARED MU S;;;;
+33B3;SQUARE MS;So;0;L;<square> 006D 0073;;;;N;SQUARED MS;;;;
+33B4;SQUARE PV;So;0;L;<square> 0070 0056;;;;N;SQUARED PV;;;;
+33B5;SQUARE NV;So;0;L;<square> 006E 0056;;;;N;SQUARED NV;;;;
+33B6;SQUARE MU V;So;0;L;<square> 03BC 0056;;;;N;SQUARED MU V;;;;
+33B7;SQUARE MV;So;0;L;<square> 006D 0056;;;;N;SQUARED MV;;;;
+33B8;SQUARE KV;So;0;L;<square> 006B 0056;;;;N;SQUARED KV;;;;
+33B9;SQUARE MV MEGA;So;0;L;<square> 004D 0056;;;;N;SQUARED MV MEGA;;;;
+33BA;SQUARE PW;So;0;L;<square> 0070 0057;;;;N;SQUARED PW;;;;
+33BB;SQUARE NW;So;0;L;<square> 006E 0057;;;;N;SQUARED NW;;;;
+33BC;SQUARE MU W;So;0;L;<square> 03BC 0057;;;;N;SQUARED MU W;;;;
+33BD;SQUARE MW;So;0;L;<square> 006D 0057;;;;N;SQUARED MW;;;;
+33BE;SQUARE KW;So;0;L;<square> 006B 0057;;;;N;SQUARED KW;;;;
+33BF;SQUARE MW MEGA;So;0;L;<square> 004D 0057;;;;N;SQUARED MW MEGA;;;;
+33C0;SQUARE K OHM;So;0;L;<square> 006B 03A9;;;;N;SQUARED K OHM;;;;
+33C1;SQUARE M OHM;So;0;L;<square> 004D 03A9;;;;N;SQUARED M OHM;;;;
+33C2;SQUARE AM;So;0;L;<square> 0061 002E 006D 002E;;;;N;SQUARED AM;;;;
+33C3;SQUARE BQ;So;0;L;<square> 0042 0071;;;;N;SQUARED BQ;;;;
+33C4;SQUARE CC;So;0;L;<square> 0063 0063;;;;N;SQUARED CC;;;;
+33C5;SQUARE CD;So;0;L;<square> 0063 0064;;;;N;SQUARED CD;;;;
+33C6;SQUARE C OVER KG;So;0;L;<square> 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;;
+33C7;SQUARE CO;So;0;L;<square> 0043 006F 002E;;;;N;SQUARED CO;;;;
+33C8;SQUARE DB;So;0;L;<square> 0064 0042;;;;N;SQUARED DB;;;;
+33C9;SQUARE GY;So;0;L;<square> 0047 0079;;;;N;SQUARED GY;;;;
+33CA;SQUARE HA;So;0;L;<square> 0068 0061;;;;N;SQUARED HA;;;;
+33CB;SQUARE HP;So;0;L;<square> 0048 0050;;;;N;SQUARED HP;;;;
+33CC;SQUARE IN;So;0;L;<square> 0069 006E;;;;N;SQUARED IN;;;;
+33CD;SQUARE KK;So;0;L;<square> 004B 004B;;;;N;SQUARED KK;;;;
+33CE;SQUARE KM CAPITAL;So;0;L;<square> 004B 004D;;;;N;SQUARED KM CAPITAL;;;;
+33CF;SQUARE KT;So;0;L;<square> 006B 0074;;;;N;SQUARED KT;;;;
+33D0;SQUARE LM;So;0;L;<square> 006C 006D;;;;N;SQUARED LM;;;;
+33D1;SQUARE LN;So;0;L;<square> 006C 006E;;;;N;SQUARED LN;;;;
+33D2;SQUARE LOG;So;0;L;<square> 006C 006F 0067;;;;N;SQUARED LOG;;;;
+33D3;SQUARE LX;So;0;L;<square> 006C 0078;;;;N;SQUARED LX;;;;
+33D4;SQUARE MB SMALL;So;0;L;<square> 006D 0062;;;;N;SQUARED MB SMALL;;;;
+33D5;SQUARE MIL;So;0;L;<square> 006D 0069 006C;;;;N;SQUARED MIL;;;;
+33D6;SQUARE MOL;So;0;L;<square> 006D 006F 006C;;;;N;SQUARED MOL;;;;
+33D7;SQUARE PH;So;0;L;<square> 0050 0048;;;;N;SQUARED PH;;;;
+33D8;SQUARE PM;So;0;L;<square> 0070 002E 006D 002E;;;;N;SQUARED PM;;;;
+33D9;SQUARE PPM;So;0;L;<square> 0050 0050 004D;;;;N;SQUARED PPM;;;;
+33DA;SQUARE PR;So;0;L;<square> 0050 0052;;;;N;SQUARED PR;;;;
+33DB;SQUARE SR;So;0;L;<square> 0073 0072;;;;N;SQUARED SR;;;;
+33DC;SQUARE SV;So;0;L;<square> 0053 0076;;;;N;SQUARED SV;;;;
+33DD;SQUARE WB;So;0;L;<square> 0057 0062;;;;N;SQUARED WB;;;;
+33DE;SQUARE V OVER M;So;0;ON;<square> 0056 2215 006D;;;;N;;;;;
+33DF;SQUARE A OVER M;So;0;ON;<square> 0041 2215 006D;;;;N;;;;;
+33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L;<compat> 0031 65E5;;;;N;;;;;
+33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L;<compat> 0032 65E5;;;;N;;;;;
+33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L;<compat> 0033 65E5;;;;N;;;;;
+33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L;<compat> 0034 65E5;;;;N;;;;;
+33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L;<compat> 0035 65E5;;;;N;;;;;
+33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L;<compat> 0036 65E5;;;;N;;;;;
+33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L;<compat> 0037 65E5;;;;N;;;;;
+33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L;<compat> 0038 65E5;;;;N;;;;;
+33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L;<compat> 0039 65E5;;;;N;;;;;
+33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L;<compat> 0031 0030 65E5;;;;N;;;;;
+33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L;<compat> 0031 0031 65E5;;;;N;;;;;
+33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L;<compat> 0031 0032 65E5;;;;N;;;;;
+33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L;<compat> 0031 0033 65E5;;;;N;;;;;
+33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L;<compat> 0031 0034 65E5;;;;N;;;;;
+33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L;<compat> 0031 0035 65E5;;;;N;;;;;
+33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L;<compat> 0031 0036 65E5;;;;N;;;;;
+33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L;<compat> 0031 0037 65E5;;;;N;;;;;
+33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L;<compat> 0031 0038 65E5;;;;N;;;;;
+33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L;<compat> 0031 0039 65E5;;;;N;;;;;
+33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L;<compat> 0032 0030 65E5;;;;N;;;;;
+33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L;<compat> 0032 0031 65E5;;;;N;;;;;
+33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L;<compat> 0032 0032 65E5;;;;N;;;;;
+33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L;<compat> 0032 0033 65E5;;;;N;;;;;
+33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L;<compat> 0032 0034 65E5;;;;N;;;;;
+33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L;<compat> 0032 0035 65E5;;;;N;;;;;
+33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L;<compat> 0032 0036 65E5;;;;N;;;;;
+33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L;<compat> 0032 0037 65E5;;;;N;;;;;
+33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L;<compat> 0032 0038 65E5;;;;N;;;;;
+33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L;<compat> 0032 0039 65E5;;;;N;;;;;
+33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L;<compat> 0033 0030 65E5;;;;N;;;;;
+33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L;<compat> 0033 0031 65E5;;;;N;;;;;
+33FF;SQUARE GAL;So;0;ON;<square> 0067 0061 006C;;;;N;;;;;
+3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
+4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
+4DC0;HEXAGRAM FOR THE CREATIVE HEAVEN;So;0;ON;;;;;N;;;;;
+4DC1;HEXAGRAM FOR THE RECEPTIVE EARTH;So;0;ON;;;;;N;;;;;
+4DC2;HEXAGRAM FOR DIFFICULTY AT THE BEGINNING;So;0;ON;;;;;N;;;;;
+4DC3;HEXAGRAM FOR YOUTHFUL FOLLY;So;0;ON;;;;;N;;;;;
+4DC4;HEXAGRAM FOR WAITING;So;0;ON;;;;;N;;;;;
+4DC5;HEXAGRAM FOR CONFLICT;So;0;ON;;;;;N;;;;;
+4DC6;HEXAGRAM FOR THE ARMY;So;0;ON;;;;;N;;;;;
+4DC7;HEXAGRAM FOR HOLDING TOGETHER;So;0;ON;;;;;N;;;;;
+4DC8;HEXAGRAM FOR SMALL TAMING;So;0;ON;;;;;N;;;;;
+4DC9;HEXAGRAM FOR TREADING;So;0;ON;;;;;N;;;;;
+4DCA;HEXAGRAM FOR PEACE;So;0;ON;;;;;N;;;;;
+4DCB;HEXAGRAM FOR STANDSTILL;So;0;ON;;;;;N;;;;;
+4DCC;HEXAGRAM FOR FELLOWSHIP;So;0;ON;;;;;N;;;;;
+4DCD;HEXAGRAM FOR GREAT POSSESSION;So;0;ON;;;;;N;;;;;
+4DCE;HEXAGRAM FOR MODESTY;So;0;ON;;;;;N;;;;;
+4DCF;HEXAGRAM FOR ENTHUSIASM;So;0;ON;;;;;N;;;;;
+4DD0;HEXAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;;
+4DD1;HEXAGRAM FOR WORK ON THE DECAYED;So;0;ON;;;;;N;;;;;
+4DD2;HEXAGRAM FOR APPROACH;So;0;ON;;;;;N;;;;;
+4DD3;HEXAGRAM FOR CONTEMPLATION;So;0;ON;;;;;N;;;;;
+4DD4;HEXAGRAM FOR BITING THROUGH;So;0;ON;;;;;N;;;;;
+4DD5;HEXAGRAM FOR GRACE;So;0;ON;;;;;N;;;;;
+4DD6;HEXAGRAM FOR SPLITTING APART;So;0;ON;;;;;N;;;;;
+4DD7;HEXAGRAM FOR RETURN;So;0;ON;;;;;N;;;;;
+4DD8;HEXAGRAM FOR INNOCENCE;So;0;ON;;;;;N;;;;;
+4DD9;HEXAGRAM FOR GREAT TAMING;So;0;ON;;;;;N;;;;;
+4DDA;HEXAGRAM FOR MOUTH CORNERS;So;0;ON;;;;;N;;;;;
+4DDB;HEXAGRAM FOR GREAT PREPONDERANCE;So;0;ON;;;;;N;;;;;
+4DDC;HEXAGRAM FOR THE ABYSMAL WATER;So;0;ON;;;;;N;;;;;
+4DDD;HEXAGRAM FOR THE CLINGING FIRE;So;0;ON;;;;;N;;;;;
+4DDE;HEXAGRAM FOR INFLUENCE;So;0;ON;;;;;N;;;;;
+4DDF;HEXAGRAM FOR DURATION;So;0;ON;;;;;N;;;;;
+4DE0;HEXAGRAM FOR RETREAT;So;0;ON;;;;;N;;;;;
+4DE1;HEXAGRAM FOR GREAT POWER;So;0;ON;;;;;N;;;;;
+4DE2;HEXAGRAM FOR PROGRESS;So;0;ON;;;;;N;;;;;
+4DE3;HEXAGRAM FOR DARKENING OF THE LIGHT;So;0;ON;;;;;N;;;;;
+4DE4;HEXAGRAM FOR THE FAMILY;So;0;ON;;;;;N;;;;;
+4DE5;HEXAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;;
+4DE6;HEXAGRAM FOR OBSTRUCTION;So;0;ON;;;;;N;;;;;
+4DE7;HEXAGRAM FOR DELIVERANCE;So;0;ON;;;;;N;;;;;
+4DE8;HEXAGRAM FOR DECREASE;So;0;ON;;;;;N;;;;;
+4DE9;HEXAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;;
+4DEA;HEXAGRAM FOR BREAKTHROUGH;So;0;ON;;;;;N;;;;;
+4DEB;HEXAGRAM FOR COMING TO MEET;So;0;ON;;;;;N;;;;;
+4DEC;HEXAGRAM FOR GATHERING TOGETHER;So;0;ON;;;;;N;;;;;
+4DED;HEXAGRAM FOR PUSHING UPWARD;So;0;ON;;;;;N;;;;;
+4DEE;HEXAGRAM FOR OPPRESSION;So;0;ON;;;;;N;;;;;
+4DEF;HEXAGRAM FOR THE WELL;So;0;ON;;;;;N;;;;;
+4DF0;HEXAGRAM FOR REVOLUTION;So;0;ON;;;;;N;;;;;
+4DF1;HEXAGRAM FOR THE CAULDRON;So;0;ON;;;;;N;;;;;
+4DF2;HEXAGRAM FOR THE AROUSING THUNDER;So;0;ON;;;;;N;;;;;
+4DF3;HEXAGRAM FOR THE KEEPING STILL MOUNTAIN;So;0;ON;;;;;N;;;;;
+4DF4;HEXAGRAM FOR DEVELOPMENT;So;0;ON;;;;;N;;;;;
+4DF5;HEXAGRAM FOR THE MARRYING MAIDEN;So;0;ON;;;;;N;;;;;
+4DF6;HEXAGRAM FOR ABUNDANCE;So;0;ON;;;;;N;;;;;
+4DF7;HEXAGRAM FOR THE WANDERER;So;0;ON;;;;;N;;;;;
+4DF8;HEXAGRAM FOR THE GENTLE WIND;So;0;ON;;;;;N;;;;;
+4DF9;HEXAGRAM FOR THE JOYOUS LAKE;So;0;ON;;;;;N;;;;;
+4DFA;HEXAGRAM FOR DISPERSION;So;0;ON;;;;;N;;;;;
+4DFB;HEXAGRAM FOR LIMITATION;So;0;ON;;;;;N;;;;;
+4DFC;HEXAGRAM FOR INNER TRUTH;So;0;ON;;;;;N;;;;;
+4DFD;HEXAGRAM FOR SMALL PREPONDERANCE;So;0;ON;;;;;N;;;;;
+4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;;
+4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;;
+4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;;
+9FCB;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
+A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;;
+A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;;
+A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;;
+A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;;
+A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;;
+A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;;
+A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;;
+A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;;
+A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;;
+A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;;
+A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;;
+A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;;
+A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;;
+A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;;
+A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;;
+A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;;
+A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;;
+A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;;
+A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;;
+A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;;
+A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;;
+A015;YI SYLLABLE WU;Lm;0;L;;;;;N;;;;;
+A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;;
+A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;;
+A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;;
+A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;;
+A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;;
+A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;;
+A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;;
+A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;;
+A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;;
+A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;;
+A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;;
+A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;;
+A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;;
+A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;;
+A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;;
+A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;;
+A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;;
+A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;;
+A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;;
+A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;;
+A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;;
+A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;;
+A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;;
+A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;;
+A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;;
+A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;;
+A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;;
+A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;;
+A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;;
+A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;;
+A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;;
+A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;;
+A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;;
+A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;;
+A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;;
+A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;;
+A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;;
+A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;;
+A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;;
+A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;;
+A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;;
+A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;;
+A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;;
+A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;;
+A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;;
+A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;;
+A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;;
+A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;;
+A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;;
+A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;;
+A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;;
+A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;;
+A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;;
+A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;;
+A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;;
+A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;;
+A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;;
+A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;;
+A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;;
+A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;;
+A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;;
+A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;;
+A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;;
+A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;;
+A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;;
+A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;;
+A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;;
+A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;;
+A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;;
+A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;;
+A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;;
+A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;;
+A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;;
+A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;;
+A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;;
+A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;;
+A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;;
+A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;;
+A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;;
+A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;;
+A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;;
+A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;;
+A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;;
+A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;;
+A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;;
+A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;;
+A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;;
+A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;;
+A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;;
+A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;;
+A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;;
+A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;;
+A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;;
+A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;;
+A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;;
+A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;;
+A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;;
+A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;;
+A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;;
+A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;;
+A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;;
+A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;;
+A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;;
+A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;;
+A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;;
+A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;;
+A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;;
+A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;;
+A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;;
+A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;;
+A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;;
+A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;;
+A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;;
+A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;;
+A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;;
+A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;;
+A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;;
+A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;;
+A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;;
+A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;;
+A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;;
+A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;;
+A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;;
+A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;;
+A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;;
+A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;;
+A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;;
+A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;;
+A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;;
+A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;;
+A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;;
+A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;;
+A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;;
+A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;;
+A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;;
+A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;;
+A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;;
+A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;;
+A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;;
+A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;;
+A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;;
+A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;;
+A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;;
+A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;;
+A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;;
+A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;;
+A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;;
+A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;;
+A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;;
+A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;;
+A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;;
+A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;;
+A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;;
+A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;;
+A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;;
+A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;;
+A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;;
+A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;;
+A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;;
+A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;;
+A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;;
+A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;;
+A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;;
+A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;;
+A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;;
+A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;;
+A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;;
+A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;;
+A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;;
+A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;;
+A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;;
+A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;;
+A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;;
+A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;;
+A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;;
+A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;;
+A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;;
+A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;;
+A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;;
+A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;;
+A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;;
+A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;;
+A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;;
+A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;;
+A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;;
+A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;;
+A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;;
+A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;;
+A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;;
+A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;;
+A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;;
+A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;;
+A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;;
+A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;;
+A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;;
+A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;;
+A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;;
+A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;;
+A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;;
+A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;;
+A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;;
+A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;;
+A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;;
+A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;;
+A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;;
+A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;;
+A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;;
+A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;;
+A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;;
+A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;;
+A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;;
+A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;;
+A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;;
+A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;;
+A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;;
+A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;;
+A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;;
+A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;;
+A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;;
+A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;;
+A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;;
+A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;;
+A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;;
+A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;;
+A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;;
+A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;;
+A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;;
+A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;;
+A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;;
+A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;;
+A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;;
+A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;;
+A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;;
+A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;;
+A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;;
+A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;;
+A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;;
+A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;;
+A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;;
+A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;;
+A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;;
+A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;;
+A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;;
+A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;;
+A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;;
+A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;;
+A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;;
+A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;;
+A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;;
+A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;;
+A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;;
+A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;;
+A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;;
+A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;;
+A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;;
+A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;;
+A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;;
+A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;;
+A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;;
+A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;;
+A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;;
+A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;;
+A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;;
+A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;;
+A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;;
+A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;;
+A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;;
+A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;;
+A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;;
+A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;;
+A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;;
+A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;;
+A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;;
+A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;;
+A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;;
+A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;;
+A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;;
+A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;;
+A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;;
+A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;;
+A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;;
+A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;;
+A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;;
+A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;;
+A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;;
+A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;;
+A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;;
+A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;;
+A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;;
+A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;;
+A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;;
+A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;;
+A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;;
+A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;;
+A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;;
+A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;;
+A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;;
+A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;;
+A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;;
+A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;;
+A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;;
+A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;;
+A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;;
+A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;;
+A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;;
+A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;;
+A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;;
+A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;;
+A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;;
+A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;;
+A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;;
+A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;;
+A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;;
+A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;;
+A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;;
+A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;;
+A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;;
+A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;;
+A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;;
+A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;;
+A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;;
+A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;;
+A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;;
+A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;;
+A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;;
+A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;;
+A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;;
+A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;;
+A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;;
+A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;;
+A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;;
+A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;;
+A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;;
+A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;;
+A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;;
+A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;;
+A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;;
+A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;;
+A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;;
+A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;;
+A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;;
+A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;;
+A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;;
+A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;;
+A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;;
+A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;;
+A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;;
+A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;;
+A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;;
+A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;;
+A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;;
+A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;;
+A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;;
+A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;;
+A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;;
+A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;;
+A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;;
+A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;;
+A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;;
+A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;;
+A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;;
+A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;;
+A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;;
+A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;;
+A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;;
+A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;;
+A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;;
+A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;;
+A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;;
+A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;;
+A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;;
+A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;;
+A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;;
+A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;;
+A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;;
+A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;;
+A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;;
+A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;;
+A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;;
+A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;;
+A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;;
+A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;;
+A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;;
+A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;;
+A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;;
+A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;;
+A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;;
+A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;;
+A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;;
+A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;;
+A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;;
+A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;;
+A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;;
+A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;;
+A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;;
+A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;;
+A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;;
+A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;;
+A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;;
+A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;;
+A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;;
+A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;;
+A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;;
+A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;;
+A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;;
+A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;;
+A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;;
+A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;;
+A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;;
+A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;;
+A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;;
+A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;;
+A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;;
+A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;;
+A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;;
+A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;;
+A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;;
+A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;;
+A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;;
+A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;;
+A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;;
+A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;;
+A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;;
+A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;;
+A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;;
+A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;;
+A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;;
+A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;;
+A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;;
+A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;;
+A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;;
+A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;;
+A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;;
+A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;;
+A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;;
+A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;;
+A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;;
+A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;;
+A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;;
+A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;;
+A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;;
+A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;;
+A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;;
+A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;;
+A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;;
+A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;;
+A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;;
+A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;;
+A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;;
+A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;;
+A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;;
+A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;;
+A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;;
+A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;;
+A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;;
+A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;;
+A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;;
+A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;;
+A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;;
+A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;;
+A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;;
+A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;;
+A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;;
+A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;;
+A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;;
+A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;;
+A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;;
+A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;;
+A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;;
+A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;;
+A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;;
+A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;;
+A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;;
+A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;;
+A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;;
+A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;;
+A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;;
+A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;;
+A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;;
+A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;;
+A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;;
+A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;;
+A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;;
+A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;;
+A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;;
+A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;;
+A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;;
+A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;;
+A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;;
+A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;;
+A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;;
+A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;;
+A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;;
+A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;;
+A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;;
+A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;;
+A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;;
+A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;;
+A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;;
+A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;;
+A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;;
+A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;;
+A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;;
+A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;;
+A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;;
+A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;;
+A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;;
+A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;;
+A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;;
+A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;;
+A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;;
+A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;;
+A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;;
+A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;;
+A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;;
+A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;;
+A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;;
+A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;;
+A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;;
+A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;;
+A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;;
+A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;;
+A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;;
+A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;;
+A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;;
+A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;;
+A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;;
+A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;;
+A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;;
+A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;;
+A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;;
+A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;;
+A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;;
+A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;;
+A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;;
+A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;;
+A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;;
+A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;;
+A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;;
+A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;;
+A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;;
+A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;;
+A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;;
+A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;;
+A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;;
+A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;;
+A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;;
+A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;;
+A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;;
+A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;;
+A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;;
+A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;;
+A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;;
+A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;;
+A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;;
+A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;;
+A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;;
+A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;;
+A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;;
+A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;;
+A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;;
+A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;;
+A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;;
+A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;;
+A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;;
+A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;;
+A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;;
+A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;;
+A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;;
+A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;;
+A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;;
+A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;;
+A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;;
+A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;;
+A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;;
+A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;;
+A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;;
+A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;;
+A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;;
+A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;;
+A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;;
+A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;;
+A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;;
+A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;;
+A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;;
+A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;;
+A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;;
+A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;;
+A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;;
+A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;;
+A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;;
+A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;;
+A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;;
+A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;;
+A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;;
+A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;;
+A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;;
+A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;;
+A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;;
+A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;;
+A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;;
+A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;;
+A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;;
+A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;;
+A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;;
+A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;;
+A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;;
+A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;;
+A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;;
+A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;;
+A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;;
+A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;;
+A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;;
+A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;;
+A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;;
+A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;;
+A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;;
+A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;;
+A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;;
+A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;;
+A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;;
+A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;;
+A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;;
+A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;;
+A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;;
+A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;;
+A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;;
+A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;;
+A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;;
+A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;;
+A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;;
+A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;;
+A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;;
+A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;;
+A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;;
+A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;;
+A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;;
+A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;;
+A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;;
+A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;;
+A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;;
+A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;;
+A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;;
+A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;;
+A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;;
+A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;;
+A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;;
+A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;;
+A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;;
+A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;;
+A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;;
+A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;;
+A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;;
+A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;;
+A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;;
+A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;;
+A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;;
+A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;;
+A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;;
+A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;;
+A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;;
+A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;;
+A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;;
+A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;;
+A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;;
+A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;;
+A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;;
+A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;;
+A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;;
+A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;;
+A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;;
+A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;;
+A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;;
+A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;;
+A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;;
+A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;;
+A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;;
+A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;;
+A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;;
+A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;;
+A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;;
+A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;;
+A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;;
+A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;;
+A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;;
+A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;;
+A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;;
+A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;;
+A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;;
+A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;;
+A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;;
+A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;;
+A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;;
+A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;;
+A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;;
+A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;;
+A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;;
+A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;;
+A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;;
+A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;;
+A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;;
+A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;;
+A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;;
+A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;;
+A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;;
+A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;;
+A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;;
+A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;;
+A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;;
+A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;;
+A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;;
+A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;;
+A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;;
+A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;;
+A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;;
+A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;;
+A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;;
+A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;;
+A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;;
+A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;;
+A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;;
+A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;;
+A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;;
+A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;;
+A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;;
+A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;;
+A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;;
+A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;;
+A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;;
+A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;;
+A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;;
+A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;;
+A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;;
+A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;;
+A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;;
+A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;;
+A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;;
+A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;;
+A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;;
+A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;;
+A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;;
+A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;;
+A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;;
+A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;;
+A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;;
+A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;;
+A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;;
+A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;;
+A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;;
+A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;;
+A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;;
+A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;;
+A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;;
+A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;;
+A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;;
+A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;;
+A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;;
+A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;;
+A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;;
+A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;;
+A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;;
+A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;;
+A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;;
+A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;;
+A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;;
+A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;;
+A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;;
+A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;;
+A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;;
+A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;;
+A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;;
+A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;;
+A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;;
+A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;;
+A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;;
+A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;;
+A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;;
+A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;;
+A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;;
+A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;;
+A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;;
+A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;;
+A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;;
+A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;;
+A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;;
+A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;;
+A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;;
+A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;;
+A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;;
+A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;;
+A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;;
+A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;;
+A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;;
+A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;;
+A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;;
+A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;;
+A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;;
+A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;;
+A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;;
+A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;;
+A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;;
+A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;;
+A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;;
+A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;;
+A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;;
+A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;;
+A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;;
+A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;;
+A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;;
+A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;;
+A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;;
+A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;;
+A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;;
+A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;;
+A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;;
+A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;;
+A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;;
+A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;;
+A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;;
+A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;;
+A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;;
+A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;;
+A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;;
+A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;;
+A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;;
+A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;;
+A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;;
+A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;;
+A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;;
+A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;;
+A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;;
+A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;;
+A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;;
+A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;;
+A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;;
+A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;;
+A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;;
+A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;;
+A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;;
+A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;;
+A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;;
+A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;;
+A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;;
+A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;;
+A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;;
+A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;;
+A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;;
+A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;;
+A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;;
+A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;;
+A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;;
+A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;;
+A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;;
+A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;;
+A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;;
+A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;;
+A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;;
+A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;;
+A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;;
+A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;;
+A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;;
+A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;;
+A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;;
+A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;;
+A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;;
+A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;;
+A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;;
+A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;;
+A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;;
+A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;;
+A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;;
+A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;;
+A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;;
+A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;;
+A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;;
+A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;;
+A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;;
+A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;;
+A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;;
+A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;;
+A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;;
+A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;;
+A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;;
+A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;;
+A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;;
+A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;;
+A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;;
+A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;;
+A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;;
+A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;;
+A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;;
+A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;;
+A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;;
+A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;;
+A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;;
+A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;;
+A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;;
+A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;;
+A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;;
+A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;;
+A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;;
+A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;;
+A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;;
+A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;;
+A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;;
+A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;;
+A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;;
+A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;;
+A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;;
+A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;;
+A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;;
+A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;;
+A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;;
+A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;;
+A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;;
+A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;;
+A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;;
+A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;;
+A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;;
+A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;;
+A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;;
+A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;;
+A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;;
+A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;;
+A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;;
+A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;;
+A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;;
+A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;;
+A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;;
+A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;;
+A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;;
+A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;;
+A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;;
+A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;;
+A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;;
+A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;;
+A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;;
+A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;;
+A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;;
+A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;;
+A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;;
+A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;;
+A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;;
+A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;;
+A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;;
+A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;;
+A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;;
+A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;;
+A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;;
+A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;;
+A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;;
+A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;;
+A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;;
+A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;;
+A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;;
+A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;;
+A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;;
+A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;;
+A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;;
+A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;;
+A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;;
+A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;;
+A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;;
+A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;;
+A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;;
+A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;;
+A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;;
+A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;;
+A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;;
+A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;;
+A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;;
+A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;;
+A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;;
+A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;;
+A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;;
+A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;;
+A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;;
+A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;;
+A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;;
+A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;;
+A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;;
+A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;;
+A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;;
+A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;;
+A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;;
+A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;;
+A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;;
+A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;;
+A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;;
+A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;;
+A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;;
+A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;;
+A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;;
+A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;;
+A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;;
+A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;;
+A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;;
+A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;;
+A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;;
+A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;;
+A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;;
+A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;;
+A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;;
+A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;;
+A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;;
+A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;;
+A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;;
+A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;;
+A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;;
+A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;;
+A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;;
+A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;;
+A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;;
+A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;;
+A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;;
+A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;;
+A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;;
+A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;;
+A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;;
+A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;;
+A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;;
+A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;;
+A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;;
+A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;;
+A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;;
+A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;;
+A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;;
+A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;;
+A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;;
+A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;;
+A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;;
+A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;;
+A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;;
+A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;;
+A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;;
+A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;;
+A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;;
+A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;;
+A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;;
+A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;;
+A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;;
+A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;;
+A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;;
+A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;;
+A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;;
+A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;;
+A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;;
+A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;;
+A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;;
+A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;;
+A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;;
+A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;;
+A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;;
+A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;;
+A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;;
+A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;;
+A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;;
+A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;;
+A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;;
+A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;;
+A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;;
+A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;;
+A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;;
+A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;;
+A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;;
+A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;;
+A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;;
+A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;;
+A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;;
+A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;;
+A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;;
+A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;;
+A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;;
+A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;;
+A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;;
+A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;;
+A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;;
+A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;;
+A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;;
+A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;;
+A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;;
+A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;;
+A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;;
+A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;;
+A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;;
+A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;;
+A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;;
+A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;;
+A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;;
+A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;;
+A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;;
+A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;;
+A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;;
+A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;;
+A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;;
+A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;;
+A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;;
+A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;;
+A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;;
+A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;;
+A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;;
+A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;;
+A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;;
+A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;;
+A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;;
+A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;;
+A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;;
+A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;;
+A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;;
+A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;;
+A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;;
+A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;;
+A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;;
+A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;;
+A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;;
+A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;;
+A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;;
+A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;;
+A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;;
+A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;;
+A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;;
+A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;;
+A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;;
+A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;;
+A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;;
+A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;;
+A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;;
+A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;;
+A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;;
+A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;;
+A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;;
+A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;;
+A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;;
+A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;;
+A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;;
+A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;;
+A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;;
+A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;;
+A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;;
+A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;;
+A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;;
+A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;;
+A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;;
+A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;;
+A491;YI RADICAL LI;So;0;ON;;;;;N;;;;;
+A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;;
+A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;;
+A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;;
+A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;;
+A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;;
+A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;;
+A498;YI RADICAL MI;So;0;ON;;;;;N;;;;;
+A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;;
+A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;;
+A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;;
+A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;;
+A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;;
+A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;;
+A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;;
+A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;;
+A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;;
+A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;;
+A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;;
+A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;;
+A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;;
+A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;;
+A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;;
+A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;;
+A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;;
+A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;;
+A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;;
+A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;;
+A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;;
+A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;;
+A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;;
+A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;;
+A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;;
+A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;;
+A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;;
+A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;;
+A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;;
+A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;;
+A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;;
+A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;;
+A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;;
+A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;;
+A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;;
+A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;;
+A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;;
+A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;;
+A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;;
+A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;;
+A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;;
+A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;;
+A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;;
+A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;;
+A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;;
+A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;;
+A4D0;LISU LETTER BA;Lo;0;L;;;;;N;;;;;
+A4D1;LISU LETTER PA;Lo;0;L;;;;;N;;;;;
+A4D2;LISU LETTER PHA;Lo;0;L;;;;;N;;;;;
+A4D3;LISU LETTER DA;Lo;0;L;;;;;N;;;;;
+A4D4;LISU LETTER TA;Lo;0;L;;;;;N;;;;;
+A4D5;LISU LETTER THA;Lo;0;L;;;;;N;;;;;
+A4D6;LISU LETTER GA;Lo;0;L;;;;;N;;;;;
+A4D7;LISU LETTER KA;Lo;0;L;;;;;N;;;;;
+A4D8;LISU LETTER KHA;Lo;0;L;;;;;N;;;;;
+A4D9;LISU LETTER JA;Lo;0;L;;;;;N;;;;;
+A4DA;LISU LETTER CA;Lo;0;L;;;;;N;;;;;
+A4DB;LISU LETTER CHA;Lo;0;L;;;;;N;;;;;
+A4DC;LISU LETTER DZA;Lo;0;L;;;;;N;;;;;
+A4DD;LISU LETTER TSA;Lo;0;L;;;;;N;;;;;
+A4DE;LISU LETTER TSHA;Lo;0;L;;;;;N;;;;;
+A4DF;LISU LETTER MA;Lo;0;L;;;;;N;;;;;
+A4E0;LISU LETTER NA;Lo;0;L;;;;;N;;;;;
+A4E1;LISU LETTER LA;Lo;0;L;;;;;N;;;;;
+A4E2;LISU LETTER SA;Lo;0;L;;;;;N;;;;;
+A4E3;LISU LETTER ZHA;Lo;0;L;;;;;N;;;;;
+A4E4;LISU LETTER ZA;Lo;0;L;;;;;N;;;;;
+A4E5;LISU LETTER NGA;Lo;0;L;;;;;N;;;;;
+A4E6;LISU LETTER HA;Lo;0;L;;;;;N;;;;;
+A4E7;LISU LETTER XA;Lo;0;L;;;;;N;;;;;
+A4E8;LISU LETTER HHA;Lo;0;L;;;;;N;;;;;
+A4E9;LISU LETTER FA;Lo;0;L;;;;;N;;;;;
+A4EA;LISU LETTER WA;Lo;0;L;;;;;N;;;;;
+A4EB;LISU LETTER SHA;Lo;0;L;;;;;N;;;;;
+A4EC;LISU LETTER YA;Lo;0;L;;;;;N;;;;;
+A4ED;LISU LETTER GHA;Lo;0;L;;;;;N;;;;;
+A4EE;LISU LETTER A;Lo;0;L;;;;;N;;;;;
+A4EF;LISU LETTER AE;Lo;0;L;;;;;N;;;;;
+A4F0;LISU LETTER E;Lo;0;L;;;;;N;;;;;
+A4F1;LISU LETTER EU;Lo;0;L;;;;;N;;;;;
+A4F2;LISU LETTER I;Lo;0;L;;;;;N;;;;;
+A4F3;LISU LETTER O;Lo;0;L;;;;;N;;;;;
+A4F4;LISU LETTER U;Lo;0;L;;;;;N;;;;;
+A4F5;LISU LETTER UE;Lo;0;L;;;;;N;;;;;
+A4F6;LISU LETTER UH;Lo;0;L;;;;;N;;;;;
+A4F7;LISU LETTER OE;Lo;0;L;;;;;N;;;;;
+A4F8;LISU LETTER TONE MYA TI;Lm;0;L;;;;;N;;;;;
+A4F9;LISU LETTER TONE NA PO;Lm;0;L;;;;;N;;;;;
+A4FA;LISU LETTER TONE MYA CYA;Lm;0;L;;;;;N;;;;;
+A4FB;LISU LETTER TONE MYA BO;Lm;0;L;;;;;N;;;;;
+A4FC;LISU LETTER TONE MYA NA;Lm;0;L;;;;;N;;;;;
+A4FD;LISU LETTER TONE MYA JEU;Lm;0;L;;;;;N;;;;;
+A4FE;LISU PUNCTUATION COMMA;Po;0;L;;;;;N;;;;;
+A4FF;LISU PUNCTUATION FULL STOP;Po;0;L;;;;;N;;;;;
+A500;VAI SYLLABLE EE;Lo;0;L;;;;;N;;;;;
+A501;VAI SYLLABLE EEN;Lo;0;L;;;;;N;;;;;
+A502;VAI SYLLABLE HEE;Lo;0;L;;;;;N;;;;;
+A503;VAI SYLLABLE WEE;Lo;0;L;;;;;N;;;;;
+A504;VAI SYLLABLE WEEN;Lo;0;L;;;;;N;;;;;
+A505;VAI SYLLABLE PEE;Lo;0;L;;;;;N;;;;;
+A506;VAI SYLLABLE BHEE;Lo;0;L;;;;;N;;;;;
+A507;VAI SYLLABLE BEE;Lo;0;L;;;;;N;;;;;
+A508;VAI SYLLABLE MBEE;Lo;0;L;;;;;N;;;;;
+A509;VAI SYLLABLE KPEE;Lo;0;L;;;;;N;;;;;
+A50A;VAI SYLLABLE MGBEE;Lo;0;L;;;;;N;;;;;
+A50B;VAI SYLLABLE GBEE;Lo;0;L;;;;;N;;;;;
+A50C;VAI SYLLABLE FEE;Lo;0;L;;;;;N;;;;;
+A50D;VAI SYLLABLE VEE;Lo;0;L;;;;;N;;;;;
+A50E;VAI SYLLABLE TEE;Lo;0;L;;;;;N;;;;;
+A50F;VAI SYLLABLE THEE;Lo;0;L;;;;;N;;;;;
+A510;VAI SYLLABLE DHEE;Lo;0;L;;;;;N;;;;;
+A511;VAI SYLLABLE DHHEE;Lo;0;L;;;;;N;;;;;
+A512;VAI SYLLABLE LEE;Lo;0;L;;;;;N;;;;;
+A513;VAI SYLLABLE REE;Lo;0;L;;;;;N;;;;;
+A514;VAI SYLLABLE DEE;Lo;0;L;;;;;N;;;;;
+A515;VAI SYLLABLE NDEE;Lo;0;L;;;;;N;;;;;
+A516;VAI SYLLABLE SEE;Lo;0;L;;;;;N;;;;;
+A517;VAI SYLLABLE SHEE;Lo;0;L;;;;;N;;;;;
+A518;VAI SYLLABLE ZEE;Lo;0;L;;;;;N;;;;;
+A519;VAI SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;;
+A51A;VAI SYLLABLE CEE;Lo;0;L;;;;;N;;;;;
+A51B;VAI SYLLABLE JEE;Lo;0;L;;;;;N;;;;;
+A51C;VAI SYLLABLE NJEE;Lo;0;L;;;;;N;;;;;
+A51D;VAI SYLLABLE YEE;Lo;0;L;;;;;N;;;;;
+A51E;VAI SYLLABLE KEE;Lo;0;L;;;;;N;;;;;
+A51F;VAI SYLLABLE NGGEE;Lo;0;L;;;;;N;;;;;
+A520;VAI SYLLABLE GEE;Lo;0;L;;;;;N;;;;;
+A521;VAI SYLLABLE MEE;Lo;0;L;;;;;N;;;;;
+A522;VAI SYLLABLE NEE;Lo;0;L;;;;;N;;;;;
+A523;VAI SYLLABLE NYEE;Lo;0;L;;;;;N;;;;;
+A524;VAI SYLLABLE I;Lo;0;L;;;;;N;;;;;
+A525;VAI SYLLABLE IN;Lo;0;L;;;;;N;;;;;
+A526;VAI SYLLABLE HI;Lo;0;L;;;;;N;;;;;
+A527;VAI SYLLABLE HIN;Lo;0;L;;;;;N;;;;;
+A528;VAI SYLLABLE WI;Lo;0;L;;;;;N;;;;;
+A529;VAI SYLLABLE WIN;Lo;0;L;;;;;N;;;;;
+A52A;VAI SYLLABLE PI;Lo;0;L;;;;;N;;;;;
+A52B;VAI SYLLABLE BHI;Lo;0;L;;;;;N;;;;;
+A52C;VAI SYLLABLE BI;Lo;0;L;;;;;N;;;;;
+A52D;VAI SYLLABLE MBI;Lo;0;L;;;;;N;;;;;
+A52E;VAI SYLLABLE KPI;Lo;0;L;;;;;N;;;;;
+A52F;VAI SYLLABLE MGBI;Lo;0;L;;;;;N;;;;;
+A530;VAI SYLLABLE GBI;Lo;0;L;;;;;N;;;;;
+A531;VAI SYLLABLE FI;Lo;0;L;;;;;N;;;;;
+A532;VAI SYLLABLE VI;Lo;0;L;;;;;N;;;;;
+A533;VAI SYLLABLE TI;Lo;0;L;;;;;N;;;;;
+A534;VAI SYLLABLE THI;Lo;0;L;;;;;N;;;;;
+A535;VAI SYLLABLE DHI;Lo;0;L;;;;;N;;;;;
+A536;VAI SYLLABLE DHHI;Lo;0;L;;;;;N;;;;;
+A537;VAI SYLLABLE LI;Lo;0;L;;;;;N;;;;;
+A538;VAI SYLLABLE RI;Lo;0;L;;;;;N;;;;;
+A539;VAI SYLLABLE DI;Lo;0;L;;;;;N;;;;;
+A53A;VAI SYLLABLE NDI;Lo;0;L;;;;;N;;;;;
+A53B;VAI SYLLABLE SI;Lo;0;L;;;;;N;;;;;
+A53C;VAI SYLLABLE SHI;Lo;0;L;;;;;N;;;;;
+A53D;VAI SYLLABLE ZI;Lo;0;L;;;;;N;;;;;
+A53E;VAI SYLLABLE ZHI;Lo;0;L;;;;;N;;;;;
+A53F;VAI SYLLABLE CI;Lo;0;L;;;;;N;;;;;
+A540;VAI SYLLABLE JI;Lo;0;L;;;;;N;;;;;
+A541;VAI SYLLABLE NJI;Lo;0;L;;;;;N;;;;;
+A542;VAI SYLLABLE YI;Lo;0;L;;;;;N;;;;;
+A543;VAI SYLLABLE KI;Lo;0;L;;;;;N;;;;;
+A544;VAI SYLLABLE NGGI;Lo;0;L;;;;;N;;;;;
+A545;VAI SYLLABLE GI;Lo;0;L;;;;;N;;;;;
+A546;VAI SYLLABLE MI;Lo;0;L;;;;;N;;;;;
+A547;VAI SYLLABLE NI;Lo;0;L;;;;;N;;;;;
+A548;VAI SYLLABLE NYI;Lo;0;L;;;;;N;;;;;
+A549;VAI SYLLABLE A;Lo;0;L;;;;;N;;;;;
+A54A;VAI SYLLABLE AN;Lo;0;L;;;;;N;;;;;
+A54B;VAI SYLLABLE NGAN;Lo;0;L;;;;;N;;;;;
+A54C;VAI SYLLABLE HA;Lo;0;L;;;;;N;;;;;
+A54D;VAI SYLLABLE HAN;Lo;0;L;;;;;N;;;;;
+A54E;VAI SYLLABLE WA;Lo;0;L;;;;;N;;;;;
+A54F;VAI SYLLABLE WAN;Lo;0;L;;;;;N;;;;;
+A550;VAI SYLLABLE PA;Lo;0;L;;;;;N;;;;;
+A551;VAI SYLLABLE BHA;Lo;0;L;;;;;N;;;;;
+A552;VAI SYLLABLE BA;Lo;0;L;;;;;N;;;;;
+A553;VAI SYLLABLE MBA;Lo;0;L;;;;;N;;;;;
+A554;VAI SYLLABLE KPA;Lo;0;L;;;;;N;;;;;
+A555;VAI SYLLABLE KPAN;Lo;0;L;;;;;N;;;;;
+A556;VAI SYLLABLE MGBA;Lo;0;L;;;;;N;;;;;
+A557;VAI SYLLABLE GBA;Lo;0;L;;;;;N;;;;;
+A558;VAI SYLLABLE FA;Lo;0;L;;;;;N;;;;;
+A559;VAI SYLLABLE VA;Lo;0;L;;;;;N;;;;;
+A55A;VAI SYLLABLE TA;Lo;0;L;;;;;N;;;;;
+A55B;VAI SYLLABLE THA;Lo;0;L;;;;;N;;;;;
+A55C;VAI SYLLABLE DHA;Lo;0;L;;;;;N;;;;;
+A55D;VAI SYLLABLE DHHA;Lo;0;L;;;;;N;;;;;
+A55E;VAI SYLLABLE LA;Lo;0;L;;;;;N;;;;;
+A55F;VAI SYLLABLE RA;Lo;0;L;;;;;N;;;;;
+A560;VAI SYLLABLE DA;Lo;0;L;;;;;N;;;;;
+A561;VAI SYLLABLE NDA;Lo;0;L;;;;;N;;;;;
+A562;VAI SYLLABLE SA;Lo;0;L;;;;;N;;;;;
+A563;VAI SYLLABLE SHA;Lo;0;L;;;;;N;;;;;
+A564;VAI SYLLABLE ZA;Lo;0;L;;;;;N;;;;;
+A565;VAI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;;
+A566;VAI SYLLABLE CA;Lo;0;L;;;;;N;;;;;
+A567;VAI SYLLABLE JA;Lo;0;L;;;;;N;;;;;
+A568;VAI SYLLABLE NJA;Lo;0;L;;;;;N;;;;;
+A569;VAI SYLLABLE YA;Lo;0;L;;;;;N;;;;;
+A56A;VAI SYLLABLE KA;Lo;0;L;;;;;N;;;;;
+A56B;VAI SYLLABLE KAN;Lo;0;L;;;;;N;;;;;
+A56C;VAI SYLLABLE NGGA;Lo;0;L;;;;;N;;;;;
+A56D;VAI SYLLABLE GA;Lo;0;L;;;;;N;;;;;
+A56E;VAI SYLLABLE MA;Lo;0;L;;;;;N;;;;;
+A56F;VAI SYLLABLE NA;Lo;0;L;;;;;N;;;;;
+A570;VAI SYLLABLE NYA;Lo;0;L;;;;;N;;;;;
+A571;VAI SYLLABLE OO;Lo;0;L;;;;;N;;;;;
+A572;VAI SYLLABLE OON;Lo;0;L;;;;;N;;;;;
+A573;VAI SYLLABLE HOO;Lo;0;L;;;;;N;;;;;
+A574;VAI SYLLABLE WOO;Lo;0;L;;;;;N;;;;;
+A575;VAI SYLLABLE WOON;Lo;0;L;;;;;N;;;;;
+A576;VAI SYLLABLE POO;Lo;0;L;;;;;N;;;;;
+A577;VAI SYLLABLE BHOO;Lo;0;L;;;;;N;;;;;
+A578;VAI SYLLABLE BOO;Lo;0;L;;;;;N;;;;;
+A579;VAI SYLLABLE MBOO;Lo;0;L;;;;;N;;;;;
+A57A;VAI SYLLABLE KPOO;Lo;0;L;;;;;N;;;;;
+A57B;VAI SYLLABLE MGBOO;Lo;0;L;;;;;N;;;;;
+A57C;VAI SYLLABLE GBOO;Lo;0;L;;;;;N;;;;;
+A57D;VAI SYLLABLE FOO;Lo;0;L;;;;;N;;;;;
+A57E;VAI SYLLABLE VOO;Lo;0;L;;;;;N;;;;;
+A57F;VAI SYLLABLE TOO;Lo;0;L;;;;;N;;;;;
+A580;VAI SYLLABLE THOO;Lo;0;L;;;;;N;;;;;
+A581;VAI SYLLABLE DHOO;Lo;0;L;;;;;N;;;;;
+A582;VAI SYLLABLE DHHOO;Lo;0;L;;;;;N;;;;;
+A583;VAI SYLLABLE LOO;Lo;0;L;;;;;N;;;;;
+A584;VAI SYLLABLE ROO;Lo;0;L;;;;;N;;;;;
+A585;VAI SYLLABLE DOO;Lo;0;L;;;;;N;;;;;
+A586;VAI SYLLABLE NDOO;Lo;0;L;;;;;N;;;;;
+A587;VAI SYLLABLE SOO;Lo;0;L;;;;;N;;;;;
+A588;VAI SYLLABLE SHOO;Lo;0;L;;;;;N;;;;;
+A589;VAI SYLLABLE ZOO;Lo;0;L;;;;;N;;;;;
+A58A;VAI SYLLABLE ZHOO;Lo;0;L;;;;;N;;;;;
+A58B;VAI SYLLABLE COO;Lo;0;L;;;;;N;;;;;
+A58C;VAI SYLLABLE JOO;Lo;0;L;;;;;N;;;;;
+A58D;VAI SYLLABLE NJOO;Lo;0;L;;;;;N;;;;;
+A58E;VAI SYLLABLE YOO;Lo;0;L;;;;;N;;;;;
+A58F;VAI SYLLABLE KOO;Lo;0;L;;;;;N;;;;;
+A590;VAI SYLLABLE NGGOO;Lo;0;L;;;;;N;;;;;
+A591;VAI SYLLABLE GOO;Lo;0;L;;;;;N;;;;;
+A592;VAI SYLLABLE MOO;Lo;0;L;;;;;N;;;;;
+A593;VAI SYLLABLE NOO;Lo;0;L;;;;;N;;;;;
+A594;VAI SYLLABLE NYOO;Lo;0;L;;;;;N;;;;;
+A595;VAI SYLLABLE U;Lo;0;L;;;;;N;;;;;
+A596;VAI SYLLABLE UN;Lo;0;L;;;;;N;;;;;
+A597;VAI SYLLABLE HU;Lo;0;L;;;;;N;;;;;
+A598;VAI SYLLABLE HUN;Lo;0;L;;;;;N;;;;;
+A599;VAI SYLLABLE WU;Lo;0;L;;;;;N;;;;;
+A59A;VAI SYLLABLE WUN;Lo;0;L;;;;;N;;;;;
+A59B;VAI SYLLABLE PU;Lo;0;L;;;;;N;;;;;
+A59C;VAI SYLLABLE BHU;Lo;0;L;;;;;N;;;;;
+A59D;VAI SYLLABLE BU;Lo;0;L;;;;;N;;;;;
+A59E;VAI SYLLABLE MBU;Lo;0;L;;;;;N;;;;;
+A59F;VAI SYLLABLE KPU;Lo;0;L;;;;;N;;;;;
+A5A0;VAI SYLLABLE MGBU;Lo;0;L;;;;;N;;;;;
+A5A1;VAI SYLLABLE GBU;Lo;0;L;;;;;N;;;;;
+A5A2;VAI SYLLABLE FU;Lo;0;L;;;;;N;;;;;
+A5A3;VAI SYLLABLE VU;Lo;0;L;;;;;N;;;;;
+A5A4;VAI SYLLABLE TU;Lo;0;L;;;;;N;;;;;
+A5A5;VAI SYLLABLE THU;Lo;0;L;;;;;N;;;;;
+A5A6;VAI SYLLABLE DHU;Lo;0;L;;;;;N;;;;;
+A5A7;VAI SYLLABLE DHHU;Lo;0;L;;;;;N;;;;;
+A5A8;VAI SYLLABLE LU;Lo;0;L;;;;;N;;;;;
+A5A9;VAI SYLLABLE RU;Lo;0;L;;;;;N;;;;;
+A5AA;VAI SYLLABLE DU;Lo;0;L;;;;;N;;;;;
+A5AB;VAI SYLLABLE NDU;Lo;0;L;;;;;N;;;;;
+A5AC;VAI SYLLABLE SU;Lo;0;L;;;;;N;;;;;
+A5AD;VAI SYLLABLE SHU;Lo;0;L;;;;;N;;;;;
+A5AE;VAI SYLLABLE ZU;Lo;0;L;;;;;N;;;;;
+A5AF;VAI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;;
+A5B0;VAI SYLLABLE CU;Lo;0;L;;;;;N;;;;;
+A5B1;VAI SYLLABLE JU;Lo;0;L;;;;;N;;;;;
+A5B2;VAI SYLLABLE NJU;Lo;0;L;;;;;N;;;;;
+A5B3;VAI SYLLABLE YU;Lo;0;L;;;;;N;;;;;
+A5B4;VAI SYLLABLE KU;Lo;0;L;;;;;N;;;;;
+A5B5;VAI SYLLABLE NGGU;Lo;0;L;;;;;N;;;;;
+A5B6;VAI SYLLABLE GU;Lo;0;L;;;;;N;;;;;
+A5B7;VAI SYLLABLE MU;Lo;0;L;;;;;N;;;;;
+A5B8;VAI SYLLABLE NU;Lo;0;L;;;;;N;;;;;
+A5B9;VAI SYLLABLE NYU;Lo;0;L;;;;;N;;;;;
+A5BA;VAI SYLLABLE O;Lo;0;L;;;;;N;;;;;
+A5BB;VAI SYLLABLE ON;Lo;0;L;;;;;N;;;;;
+A5BC;VAI SYLLABLE NGON;Lo;0;L;;;;;N;;;;;
+A5BD;VAI SYLLABLE HO;Lo;0;L;;;;;N;;;;;
+A5BE;VAI SYLLABLE HON;Lo;0;L;;;;;N;;;;;
+A5BF;VAI SYLLABLE WO;Lo;0;L;;;;;N;;;;;
+A5C0;VAI SYLLABLE WON;Lo;0;L;;;;;N;;;;;
+A5C1;VAI SYLLABLE PO;Lo;0;L;;;;;N;;;;;
+A5C2;VAI SYLLABLE BHO;Lo;0;L;;;;;N;;;;;
+A5C3;VAI SYLLABLE BO;Lo;0;L;;;;;N;;;;;
+A5C4;VAI SYLLABLE MBO;Lo;0;L;;;;;N;;;;;
+A5C5;VAI SYLLABLE KPO;Lo;0;L;;;;;N;;;;;
+A5C6;VAI SYLLABLE MGBO;Lo;0;L;;;;;N;;;;;
+A5C7;VAI SYLLABLE GBO;Lo;0;L;;;;;N;;;;;
+A5C8;VAI SYLLABLE GBON;Lo;0;L;;;;;N;;;;;
+A5C9;VAI SYLLABLE FO;Lo;0;L;;;;;N;;;;;
+A5CA;VAI SYLLABLE VO;Lo;0;L;;;;;N;;;;;
+A5CB;VAI SYLLABLE TO;Lo;0;L;;;;;N;;;;;
+A5CC;VAI SYLLABLE THO;Lo;0;L;;;;;N;;;;;
+A5CD;VAI SYLLABLE DHO;Lo;0;L;;;;;N;;;;;
+A5CE;VAI SYLLABLE DHHO;Lo;0;L;;;;;N;;;;;
+A5CF;VAI SYLLABLE LO;Lo;0;L;;;;;N;;;;;
+A5D0;VAI SYLLABLE RO;Lo;0;L;;;;;N;;;;;
+A5D1;VAI SYLLABLE DO;Lo;0;L;;;;;N;;;;;
+A5D2;VAI SYLLABLE NDO;Lo;0;L;;;;;N;;;;;
+A5D3;VAI SYLLABLE SO;Lo;0;L;;;;;N;;;;;
+A5D4;VAI SYLLABLE SHO;Lo;0;L;;;;;N;;;;;
+A5D5;VAI SYLLABLE ZO;Lo;0;L;;;;;N;;;;;
+A5D6;VAI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;;
+A5D7;VAI SYLLABLE CO;Lo;0;L;;;;;N;;;;;
+A5D8;VAI SYLLABLE JO;Lo;0;L;;;;;N;;;;;
+A5D9;VAI SYLLABLE NJO;Lo;0;L;;;;;N;;;;;
+A5DA;VAI SYLLABLE YO;Lo;0;L;;;;;N;;;;;
+A5DB;VAI SYLLABLE KO;Lo;0;L;;;;;N;;;;;
+A5DC;VAI SYLLABLE NGGO;Lo;0;L;;;;;N;;;;;
+A5DD;VAI SYLLABLE GO;Lo;0;L;;;;;N;;;;;
+A5DE;VAI SYLLABLE MO;Lo;0;L;;;;;N;;;;;
+A5DF;VAI SYLLABLE NO;Lo;0;L;;;;;N;;;;;
+A5E0;VAI SYLLABLE NYO;Lo;0;L;;;;;N;;;;;
+A5E1;VAI SYLLABLE E;Lo;0;L;;;;;N;;;;;
+A5E2;VAI SYLLABLE EN;Lo;0;L;;;;;N;;;;;
+A5E3;VAI SYLLABLE NGEN;Lo;0;L;;;;;N;;;;;
+A5E4;VAI SYLLABLE HE;Lo;0;L;;;;;N;;;;;
+A5E5;VAI SYLLABLE HEN;Lo;0;L;;;;;N;;;;;
+A5E6;VAI SYLLABLE WE;Lo;0;L;;;;;N;;;;;
+A5E7;VAI SYLLABLE WEN;Lo;0;L;;;;;N;;;;;
+A5E8;VAI SYLLABLE PE;Lo;0;L;;;;;N;;;;;
+A5E9;VAI SYLLABLE BHE;Lo;0;L;;;;;N;;;;;
+A5EA;VAI SYLLABLE BE;Lo;0;L;;;;;N;;;;;
+A5EB;VAI SYLLABLE MBE;Lo;0;L;;;;;N;;;;;
+A5EC;VAI SYLLABLE KPE;Lo;0;L;;;;;N;;;;;
+A5ED;VAI SYLLABLE KPEN;Lo;0;L;;;;;N;;;;;
+A5EE;VAI SYLLABLE MGBE;Lo;0;L;;;;;N;;;;;
+A5EF;VAI SYLLABLE GBE;Lo;0;L;;;;;N;;;;;
+A5F0;VAI SYLLABLE GBEN;Lo;0;L;;;;;N;;;;;
+A5F1;VAI SYLLABLE FE;Lo;0;L;;;;;N;;;;;
+A5F2;VAI SYLLABLE VE;Lo;0;L;;;;;N;;;;;
+A5F3;VAI SYLLABLE TE;Lo;0;L;;;;;N;;;;;
+A5F4;VAI SYLLABLE THE;Lo;0;L;;;;;N;;;;;
+A5F5;VAI SYLLABLE DHE;Lo;0;L;;;;;N;;;;;
+A5F6;VAI SYLLABLE DHHE;Lo;0;L;;;;;N;;;;;
+A5F7;VAI SYLLABLE LE;Lo;0;L;;;;;N;;;;;
+A5F8;VAI SYLLABLE RE;Lo;0;L;;;;;N;;;;;
+A5F9;VAI SYLLABLE DE;Lo;0;L;;;;;N;;;;;
+A5FA;VAI SYLLABLE NDE;Lo;0;L;;;;;N;;;;;
+A5FB;VAI SYLLABLE SE;Lo;0;L;;;;;N;;;;;
+A5FC;VAI SYLLABLE SHE;Lo;0;L;;;;;N;;;;;
+A5FD;VAI SYLLABLE ZE;Lo;0;L;;;;;N;;;;;
+A5FE;VAI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;;
+A5FF;VAI SYLLABLE CE;Lo;0;L;;;;;N;;;;;
+A600;VAI SYLLABLE JE;Lo;0;L;;;;;N;;;;;
+A601;VAI SYLLABLE NJE;Lo;0;L;;;;;N;;;;;
+A602;VAI SYLLABLE YE;Lo;0;L;;;;;N;;;;;
+A603;VAI SYLLABLE KE;Lo;0;L;;;;;N;;;;;
+A604;VAI SYLLABLE NGGE;Lo;0;L;;;;;N;;;;;
+A605;VAI SYLLABLE NGGEN;Lo;0;L;;;;;N;;;;;
+A606;VAI SYLLABLE GE;Lo;0;L;;;;;N;;;;;
+A607;VAI SYLLABLE GEN;Lo;0;L;;;;;N;;;;;
+A608;VAI SYLLABLE ME;Lo;0;L;;;;;N;;;;;
+A609;VAI SYLLABLE NE;Lo;0;L;;;;;N;;;;;
+A60A;VAI SYLLABLE NYE;Lo;0;L;;;;;N;;;;;
+A60B;VAI SYLLABLE NG;Lo;0;L;;;;;N;;;;;
+A60C;VAI SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;;
+A60D;VAI COMMA;Po;0;ON;;;;;N;;;;;
+A60E;VAI FULL STOP;Po;0;ON;;;;;N;;;;;
+A60F;VAI QUESTION MARK;Po;0;ON;;;;;N;;;;;
+A610;VAI SYLLABLE NDOLE FA;Lo;0;L;;;;;N;;;;;
+A611;VAI SYLLABLE NDOLE KA;Lo;0;L;;;;;N;;;;;
+A612;VAI SYLLABLE NDOLE SOO;Lo;0;L;;;;;N;;;;;
+A613;VAI SYMBOL FEENG;Lo;0;L;;;;;N;;;;;
+A614;VAI SYMBOL KEENG;Lo;0;L;;;;;N;;;;;
+A615;VAI SYMBOL TING;Lo;0;L;;;;;N;;;;;
+A616;VAI SYMBOL NII;Lo;0;L;;;;;N;;;;;
+A617;VAI SYMBOL BANG;Lo;0;L;;;;;N;;;;;
+A618;VAI SYMBOL FAA;Lo;0;L;;;;;N;;;;;
+A619;VAI SYMBOL TAA;Lo;0;L;;;;;N;;;;;
+A61A;VAI SYMBOL DANG;Lo;0;L;;;;;N;;;;;
+A61B;VAI SYMBOL DOONG;Lo;0;L;;;;;N;;;;;
+A61C;VAI SYMBOL KUNG;Lo;0;L;;;;;N;;;;;
+A61D;VAI SYMBOL TONG;Lo;0;L;;;;;N;;;;;
+A61E;VAI SYMBOL DO-O;Lo;0;L;;;;;N;;;;;
+A61F;VAI SYMBOL JONG;Lo;0;L;;;;;N;;;;;
+A620;VAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+A621;VAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+A622;VAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+A623;VAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+A624;VAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+A625;VAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+A626;VAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+A627;VAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+A628;VAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+A629;VAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+A62A;VAI SYLLABLE NDOLE MA;Lo;0;L;;;;;N;;;;;
+A62B;VAI SYLLABLE NDOLE DO;Lo;0;L;;;;;N;;;;;
+A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641;
+A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640
+A642;CYRILLIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;A643;
+A643;CYRILLIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;A642;;A642
+A644;CYRILLIC CAPITAL LETTER REVERSED DZE;Lu;0;L;;;;;N;;;;A645;
+A645;CYRILLIC SMALL LETTER REVERSED DZE;Ll;0;L;;;;;N;;;A644;;A644
+A646;CYRILLIC CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;A647;
+A647;CYRILLIC SMALL LETTER IOTA;Ll;0;L;;;;;N;;;A646;;A646
+A648;CYRILLIC CAPITAL LETTER DJERV;Lu;0;L;;;;;N;;;;A649;
+A649;CYRILLIC SMALL LETTER DJERV;Ll;0;L;;;;;N;;;A648;;A648
+A64A;CYRILLIC CAPITAL LETTER MONOGRAPH UK;Lu;0;L;;;;;N;;;;A64B;
+A64B;CYRILLIC SMALL LETTER MONOGRAPH UK;Ll;0;L;;;;;N;;;A64A;;A64A
+A64C;CYRILLIC CAPITAL LETTER BROAD OMEGA;Lu;0;L;;;;;N;;;;A64D;
+A64D;CYRILLIC SMALL LETTER BROAD OMEGA;Ll;0;L;;;;;N;;;A64C;;A64C
+A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F;
+A64F;CYRILLIC SMALL LETTER NEUTRAL YER;Ll;0;L;;;;;N;;;A64E;;A64E
+A650;CYRILLIC CAPITAL LETTER YERU WITH BACK YER;Lu;0;L;;;;;N;;;;A651;
+A651;CYRILLIC SMALL LETTER YERU WITH BACK YER;Ll;0;L;;;;;N;;;A650;;A650
+A652;CYRILLIC CAPITAL LETTER IOTIFIED YAT;Lu;0;L;;;;;N;;;;A653;
+A653;CYRILLIC SMALL LETTER IOTIFIED YAT;Ll;0;L;;;;;N;;;A652;;A652
+A654;CYRILLIC CAPITAL LETTER REVERSED YU;Lu;0;L;;;;;N;;;;A655;
+A655;CYRILLIC SMALL LETTER REVERSED YU;Ll;0;L;;;;;N;;;A654;;A654
+A656;CYRILLIC CAPITAL LETTER IOTIFIED A;Lu;0;L;;;;;N;;;;A657;
+A657;CYRILLIC SMALL LETTER IOTIFIED A;Ll;0;L;;;;;N;;;A656;;A656
+A658;CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A659;
+A659;CYRILLIC SMALL LETTER CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A658;;A658
+A65A;CYRILLIC CAPITAL LETTER BLENDED YUS;Lu;0;L;;;;;N;;;;A65B;
+A65B;CYRILLIC SMALL LETTER BLENDED YUS;Ll;0;L;;;;;N;;;A65A;;A65A
+A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D;
+A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C
+A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F;
+A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E
+A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663;
+A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662
+A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665;
+A665;CYRILLIC SMALL LETTER SOFT EL;Ll;0;L;;;;;N;;;A664;;A664
+A666;CYRILLIC CAPITAL LETTER SOFT EM;Lu;0;L;;;;;N;;;;A667;
+A667;CYRILLIC SMALL LETTER SOFT EM;Ll;0;L;;;;;N;;;A666;;A666
+A668;CYRILLIC CAPITAL LETTER MONOCULAR O;Lu;0;L;;;;;N;;;;A669;
+A669;CYRILLIC SMALL LETTER MONOCULAR O;Ll;0;L;;;;;N;;;A668;;A668
+A66A;CYRILLIC CAPITAL LETTER BINOCULAR O;Lu;0;L;;;;;N;;;;A66B;
+A66B;CYRILLIC SMALL LETTER BINOCULAR O;Ll;0;L;;;;;N;;;A66A;;A66A
+A66C;CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O;Lu;0;L;;;;;N;;;;A66D;
+A66D;CYRILLIC SMALL LETTER DOUBLE MONOCULAR O;Ll;0;L;;;;;N;;;A66C;;A66C
+A66E;CYRILLIC LETTER MULTIOCULAR O;Lo;0;L;;;;;N;;;;;
+A66F;COMBINING CYRILLIC VZMET;Mn;230;NSM;;;;;N;;;;;
+A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
+A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
+A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;;
+A673;SLAVONIC ASTERISK;Po;0;ON;;;;;N;;;;;
+A67C;COMBINING CYRILLIC KAVYKA;Mn;230;NSM;;;;;N;;;;;
+A67D;COMBINING CYRILLIC PAYEROK;Mn;230;NSM;;;;;N;;;;;
+A67E;CYRILLIC KAVYKA;Po;0;ON;;;;;N;;;;;
+A67F;CYRILLIC PAYEROK;Lm;0;ON;;;;;N;;;;;
+A680;CYRILLIC CAPITAL LETTER DWE;Lu;0;L;;;;;N;;;;A681;
+A681;CYRILLIC SMALL LETTER DWE;Ll;0;L;;;;;N;;;A680;;A680
+A682;CYRILLIC CAPITAL LETTER DZWE;Lu;0;L;;;;;N;;;;A683;
+A683;CYRILLIC SMALL LETTER DZWE;Ll;0;L;;;;;N;;;A682;;A682
+A684;CYRILLIC CAPITAL LETTER ZHWE;Lu;0;L;;;;;N;;;;A685;
+A685;CYRILLIC SMALL LETTER ZHWE;Ll;0;L;;;;;N;;;A684;;A684
+A686;CYRILLIC CAPITAL LETTER CCHE;Lu;0;L;;;;;N;;;;A687;
+A687;CYRILLIC SMALL LETTER CCHE;Ll;0;L;;;;;N;;;A686;;A686
+A688;CYRILLIC CAPITAL LETTER DZZE;Lu;0;L;;;;;N;;;;A689;
+A689;CYRILLIC SMALL LETTER DZZE;Ll;0;L;;;;;N;;;A688;;A688
+A68A;CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;A68B;
+A68B;CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;A68A;;A68A
+A68C;CYRILLIC CAPITAL LETTER TWE;Lu;0;L;;;;;N;;;;A68D;
+A68D;CYRILLIC SMALL LETTER TWE;Ll;0;L;;;;;N;;;A68C;;A68C
+A68E;CYRILLIC CAPITAL LETTER TSWE;Lu;0;L;;;;;N;;;;A68F;
+A68F;CYRILLIC SMALL LETTER TSWE;Ll;0;L;;;;;N;;;A68E;;A68E
+A690;CYRILLIC CAPITAL LETTER TSSE;Lu;0;L;;;;;N;;;;A691;
+A691;CYRILLIC SMALL LETTER TSSE;Ll;0;L;;;;;N;;;A690;;A690
+A692;CYRILLIC CAPITAL LETTER TCHE;Lu;0;L;;;;;N;;;;A693;
+A693;CYRILLIC SMALL LETTER TCHE;Ll;0;L;;;;;N;;;A692;;A692
+A694;CYRILLIC CAPITAL LETTER HWE;Lu;0;L;;;;;N;;;;A695;
+A695;CYRILLIC SMALL LETTER HWE;Ll;0;L;;;;;N;;;A694;;A694
+A696;CYRILLIC CAPITAL LETTER SHWE;Lu;0;L;;;;;N;;;;A697;
+A697;CYRILLIC SMALL LETTER SHWE;Ll;0;L;;;;;N;;;A696;;A696
+A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;;
+A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;;
+A6A2;BAMUM LETTER U;Lo;0;L;;;;;N;;;;;
+A6A3;BAMUM LETTER KU;Lo;0;L;;;;;N;;;;;
+A6A4;BAMUM LETTER EE;Lo;0;L;;;;;N;;;;;
+A6A5;BAMUM LETTER REE;Lo;0;L;;;;;N;;;;;
+A6A6;BAMUM LETTER TAE;Lo;0;L;;;;;N;;;;;
+A6A7;BAMUM LETTER O;Lo;0;L;;;;;N;;;;;
+A6A8;BAMUM LETTER NYI;Lo;0;L;;;;;N;;;;;
+A6A9;BAMUM LETTER I;Lo;0;L;;;;;N;;;;;
+A6AA;BAMUM LETTER LA;Lo;0;L;;;;;N;;;;;
+A6AB;BAMUM LETTER PA;Lo;0;L;;;;;N;;;;;
+A6AC;BAMUM LETTER RII;Lo;0;L;;;;;N;;;;;
+A6AD;BAMUM LETTER RIEE;Lo;0;L;;;;;N;;;;;
+A6AE;BAMUM LETTER LEEEE;Lo;0;L;;;;;N;;;;;
+A6AF;BAMUM LETTER MEEEE;Lo;0;L;;;;;N;;;;;
+A6B0;BAMUM LETTER TAA;Lo;0;L;;;;;N;;;;;
+A6B1;BAMUM LETTER NDAA;Lo;0;L;;;;;N;;;;;
+A6B2;BAMUM LETTER NJAEM;Lo;0;L;;;;;N;;;;;
+A6B3;BAMUM LETTER M;Lo;0;L;;;;;N;;;;;
+A6B4;BAMUM LETTER SUU;Lo;0;L;;;;;N;;;;;
+A6B5;BAMUM LETTER MU;Lo;0;L;;;;;N;;;;;
+A6B6;BAMUM LETTER SHII;Lo;0;L;;;;;N;;;;;
+A6B7;BAMUM LETTER SI;Lo;0;L;;;;;N;;;;;
+A6B8;BAMUM LETTER SHEUX;Lo;0;L;;;;;N;;;;;
+A6B9;BAMUM LETTER SEUX;Lo;0;L;;;;;N;;;;;
+A6BA;BAMUM LETTER KYEE;Lo;0;L;;;;;N;;;;;
+A6BB;BAMUM LETTER KET;Lo;0;L;;;;;N;;;;;
+A6BC;BAMUM LETTER NUAE;Lo;0;L;;;;;N;;;;;
+A6BD;BAMUM LETTER NU;Lo;0;L;;;;;N;;;;;
+A6BE;BAMUM LETTER NJUAE;Lo;0;L;;;;;N;;;;;
+A6BF;BAMUM LETTER YOQ;Lo;0;L;;;;;N;;;;;
+A6C0;BAMUM LETTER SHU;Lo;0;L;;;;;N;;;;;
+A6C1;BAMUM LETTER YUQ;Lo;0;L;;;;;N;;;;;
+A6C2;BAMUM LETTER YA;Lo;0;L;;;;;N;;;;;
+A6C3;BAMUM LETTER NSHA;Lo;0;L;;;;;N;;;;;
+A6C4;BAMUM LETTER KEUX;Lo;0;L;;;;;N;;;;;
+A6C5;BAMUM LETTER PEUX;Lo;0;L;;;;;N;;;;;
+A6C6;BAMUM LETTER NJEE;Lo;0;L;;;;;N;;;;;
+A6C7;BAMUM LETTER NTEE;Lo;0;L;;;;;N;;;;;
+A6C8;BAMUM LETTER PUE;Lo;0;L;;;;;N;;;;;
+A6C9;BAMUM LETTER WUE;Lo;0;L;;;;;N;;;;;
+A6CA;BAMUM LETTER PEE;Lo;0;L;;;;;N;;;;;
+A6CB;BAMUM LETTER FEE;Lo;0;L;;;;;N;;;;;
+A6CC;BAMUM LETTER RU;Lo;0;L;;;;;N;;;;;
+A6CD;BAMUM LETTER LU;Lo;0;L;;;;;N;;;;;
+A6CE;BAMUM LETTER MI;Lo;0;L;;;;;N;;;;;
+A6CF;BAMUM LETTER NI;Lo;0;L;;;;;N;;;;;
+A6D0;BAMUM LETTER REUX;Lo;0;L;;;;;N;;;;;
+A6D1;BAMUM LETTER RAE;Lo;0;L;;;;;N;;;;;
+A6D2;BAMUM LETTER KEN;Lo;0;L;;;;;N;;;;;
+A6D3;BAMUM LETTER NGKWAEN;Lo;0;L;;;;;N;;;;;
+A6D4;BAMUM LETTER NGGA;Lo;0;L;;;;;N;;;;;
+A6D5;BAMUM LETTER NGA;Lo;0;L;;;;;N;;;;;
+A6D6;BAMUM LETTER SHO;Lo;0;L;;;;;N;;;;;
+A6D7;BAMUM LETTER PUAE;Lo;0;L;;;;;N;;;;;
+A6D8;BAMUM LETTER FU;Lo;0;L;;;;;N;;;;;
+A6D9;BAMUM LETTER FOM;Lo;0;L;;;;;N;;;;;
+A6DA;BAMUM LETTER WA;Lo;0;L;;;;;N;;;;;
+A6DB;BAMUM LETTER NA;Lo;0;L;;;;;N;;;;;
+A6DC;BAMUM LETTER LI;Lo;0;L;;;;;N;;;;;
+A6DD;BAMUM LETTER PI;Lo;0;L;;;;;N;;;;;
+A6DE;BAMUM LETTER LOQ;Lo;0;L;;;;;N;;;;;
+A6DF;BAMUM LETTER KO;Lo;0;L;;;;;N;;;;;
+A6E0;BAMUM LETTER MBEN;Lo;0;L;;;;;N;;;;;
+A6E1;BAMUM LETTER REN;Lo;0;L;;;;;N;;;;;
+A6E2;BAMUM LETTER MEN;Lo;0;L;;;;;N;;;;;
+A6E3;BAMUM LETTER MA;Lo;0;L;;;;;N;;;;;
+A6E4;BAMUM LETTER TI;Lo;0;L;;;;;N;;;;;
+A6E5;BAMUM LETTER KI;Lo;0;L;;;;;N;;;;;
+A6E6;BAMUM LETTER MO;Nl;0;L;;;;1;N;;;;;
+A6E7;BAMUM LETTER MBAA;Nl;0;L;;;;2;N;;;;;
+A6E8;BAMUM LETTER TET;Nl;0;L;;;;3;N;;;;;
+A6E9;BAMUM LETTER KPA;Nl;0;L;;;;4;N;;;;;
+A6EA;BAMUM LETTER TEN;Nl;0;L;;;;5;N;;;;;
+A6EB;BAMUM LETTER NTUU;Nl;0;L;;;;6;N;;;;;
+A6EC;BAMUM LETTER SAMBA;Nl;0;L;;;;7;N;;;;;
+A6ED;BAMUM LETTER FAAMAE;Nl;0;L;;;;8;N;;;;;
+A6EE;BAMUM LETTER KOVUU;Nl;0;L;;;;9;N;;;;;
+A6EF;BAMUM LETTER KOGHOM;Nl;0;L;;;;0;N;;;;;
+A6F0;BAMUM COMBINING MARK KOQNDON;Mn;230;NSM;;;;;N;;;;;
+A6F1;BAMUM COMBINING MARK TUKWENTIS;Mn;230;NSM;;;;;N;;;;;
+A6F2;BAMUM NJAEMLI;Po;0;L;;;;;N;;;;;
+A6F3;BAMUM FULL STOP;Po;0;L;;;;;N;;;;;
+A6F4;BAMUM COLON;Po;0;L;;;;;N;;;;;
+A6F5;BAMUM COMMA;Po;0;L;;;;;N;;;;;
+A6F6;BAMUM SEMICOLON;Po;0;L;;;;;N;;;;;
+A6F7;BAMUM QUESTION MARK;Po;0;L;;;;;N;;;;;
+A700;MODIFIER LETTER CHINESE TONE YIN PING;Sk;0;ON;;;;;N;;;;;
+A701;MODIFIER LETTER CHINESE TONE YANG PING;Sk;0;ON;;;;;N;;;;;
+A702;MODIFIER LETTER CHINESE TONE YIN SHANG;Sk;0;ON;;;;;N;;;;;
+A703;MODIFIER LETTER CHINESE TONE YANG SHANG;Sk;0;ON;;;;;N;;;;;
+A704;MODIFIER LETTER CHINESE TONE YIN QU;Sk;0;ON;;;;;N;;;;;
+A705;MODIFIER LETTER CHINESE TONE YANG QU;Sk;0;ON;;;;;N;;;;;
+A706;MODIFIER LETTER CHINESE TONE YIN RU;Sk;0;ON;;;;;N;;;;;
+A707;MODIFIER LETTER CHINESE TONE YANG RU;Sk;0;ON;;;;;N;;;;;
+A708;MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
+A709;MODIFIER LETTER HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
+A70A;MODIFIER LETTER MID DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
+A70B;MODIFIER LETTER LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
+A70C;MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;;
+A70D;MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A70E;MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A70F;MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A710;MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A711;MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A712;MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A713;MODIFIER LETTER HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A714;MODIFIER LETTER MID LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A715;MODIFIER LETTER LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A716;MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;;
+A717;MODIFIER LETTER DOT VERTICAL BAR;Lm;0;ON;;;;;N;;;;;
+A718;MODIFIER LETTER DOT SLASH;Lm;0;ON;;;;;N;;;;;
+A719;MODIFIER LETTER DOT HORIZONTAL BAR;Lm;0;ON;;;;;N;;;;;
+A71A;MODIFIER LETTER LOWER RIGHT CORNER ANGLE;Lm;0;ON;;;;;N;;;;;
+A71B;MODIFIER LETTER RAISED UP ARROW;Lm;0;ON;;;;;N;;;;;
+A71C;MODIFIER LETTER RAISED DOWN ARROW;Lm;0;ON;;;;;N;;;;;
+A71D;MODIFIER LETTER RAISED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;;
+A71E;MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;;
+A71F;MODIFIER LETTER LOW INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;;
+A720;MODIFIER LETTER STRESS AND HIGH TONE;Sk;0;ON;;;;;N;;;;;
+A721;MODIFIER LETTER STRESS AND LOW TONE;Sk;0;ON;;;;;N;;;;;
+A722;LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF;Lu;0;L;;;;;N;;;;A723;
+A723;LATIN SMALL LETTER EGYPTOLOGICAL ALEF;Ll;0;L;;;;;N;;;A722;;A722
+A724;LATIN CAPITAL LETTER EGYPTOLOGICAL AIN;Lu;0;L;;;;;N;;;;A725;
+A725;LATIN SMALL LETTER EGYPTOLOGICAL AIN;Ll;0;L;;;;;N;;;A724;;A724
+A726;LATIN CAPITAL LETTER HENG;Lu;0;L;;;;;N;;;;A727;
+A727;LATIN SMALL LETTER HENG;Ll;0;L;;;;;N;;;A726;;A726
+A728;LATIN CAPITAL LETTER TZ;Lu;0;L;;;;;N;;;;A729;
+A729;LATIN SMALL LETTER TZ;Ll;0;L;;;;;N;;;A728;;A728
+A72A;LATIN CAPITAL LETTER TRESILLO;Lu;0;L;;;;;N;;;;A72B;
+A72B;LATIN SMALL LETTER TRESILLO;Ll;0;L;;;;;N;;;A72A;;A72A
+A72C;LATIN CAPITAL LETTER CUATRILLO;Lu;0;L;;;;;N;;;;A72D;
+A72D;LATIN SMALL LETTER CUATRILLO;Ll;0;L;;;;;N;;;A72C;;A72C
+A72E;LATIN CAPITAL LETTER CUATRILLO WITH COMMA;Lu;0;L;;;;;N;;;;A72F;
+A72F;LATIN SMALL LETTER CUATRILLO WITH COMMA;Ll;0;L;;;;;N;;;A72E;;A72E
+A730;LATIN LETTER SMALL CAPITAL F;Ll;0;L;;;;;N;;;;;
+A731;LATIN LETTER SMALL CAPITAL S;Ll;0;L;;;;;N;;;;;
+A732;LATIN CAPITAL LETTER AA;Lu;0;L;;;;;N;;;;A733;
+A733;LATIN SMALL LETTER AA;Ll;0;L;;;;;N;;;A732;;A732
+A734;LATIN CAPITAL LETTER AO;Lu;0;L;;;;;N;;;;A735;
+A735;LATIN SMALL LETTER AO;Ll;0;L;;;;;N;;;A734;;A734
+A736;LATIN CAPITAL LETTER AU;Lu;0;L;;;;;N;;;;A737;
+A737;LATIN SMALL LETTER AU;Ll;0;L;;;;;N;;;A736;;A736
+A738;LATIN CAPITAL LETTER AV;Lu;0;L;;;;;N;;;;A739;
+A739;LATIN SMALL LETTER AV;Ll;0;L;;;;;N;;;A738;;A738
+A73A;LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR;Lu;0;L;;;;;N;;;;A73B;
+A73B;LATIN SMALL LETTER AV WITH HORIZONTAL BAR;Ll;0;L;;;;;N;;;A73A;;A73A
+A73C;LATIN CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;A73D;
+A73D;LATIN SMALL LETTER AY;Ll;0;L;;;;;N;;;A73C;;A73C
+A73E;LATIN CAPITAL LETTER REVERSED C WITH DOT;Lu;0;L;;;;;N;;;;A73F;
+A73F;LATIN SMALL LETTER REVERSED C WITH DOT;Ll;0;L;;;;;N;;;A73E;;A73E
+A740;LATIN CAPITAL LETTER K WITH STROKE;Lu;0;L;;;;;N;;;;A741;
+A741;LATIN SMALL LETTER K WITH STROKE;Ll;0;L;;;;;N;;;A740;;A740
+A742;LATIN CAPITAL LETTER K WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A743;
+A743;LATIN SMALL LETTER K WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A742;;A742
+A744;LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A745;
+A745;LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE;Ll;0;L;;;;;N;;;A744;;A744
+A746;LATIN CAPITAL LETTER BROKEN L;Lu;0;L;;;;;N;;;;A747;
+A747;LATIN SMALL LETTER BROKEN L;Ll;0;L;;;;;N;;;A746;;A746
+A748;LATIN CAPITAL LETTER L WITH HIGH STROKE;Lu;0;L;;;;;N;;;;A749;
+A749;LATIN SMALL LETTER L WITH HIGH STROKE;Ll;0;L;;;;;N;;;A748;;A748
+A74A;LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY;Lu;0;L;;;;;N;;;;A74B;
+A74B;LATIN SMALL LETTER O WITH LONG STROKE OVERLAY;Ll;0;L;;;;;N;;;A74A;;A74A
+A74C;LATIN CAPITAL LETTER O WITH LOOP;Lu;0;L;;;;;N;;;;A74D;
+A74D;LATIN SMALL LETTER O WITH LOOP;Ll;0;L;;;;;N;;;A74C;;A74C
+A74E;LATIN CAPITAL LETTER OO;Lu;0;L;;;;;N;;;;A74F;
+A74F;LATIN SMALL LETTER OO;Ll;0;L;;;;;N;;;A74E;;A74E
+A750;LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A751;
+A751;LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A750;;A750
+A752;LATIN CAPITAL LETTER P WITH FLOURISH;Lu;0;L;;;;;N;;;;A753;
+A753;LATIN SMALL LETTER P WITH FLOURISH;Ll;0;L;;;;;N;;;A752;;A752
+A754;LATIN CAPITAL LETTER P WITH SQUIRREL TAIL;Lu;0;L;;;;;N;;;;A755;
+A755;LATIN SMALL LETTER P WITH SQUIRREL TAIL;Ll;0;L;;;;;N;;;A754;;A754
+A756;LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A757;
+A757;LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A756;;A756
+A758;LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A759;
+A759;LATIN SMALL LETTER Q WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A758;;A758
+A75A;LATIN CAPITAL LETTER R ROTUNDA;Lu;0;L;;;;;N;;;;A75B;
+A75B;LATIN SMALL LETTER R ROTUNDA;Ll;0;L;;;;;N;;;A75A;;A75A
+A75C;LATIN CAPITAL LETTER RUM ROTUNDA;Lu;0;L;;;;;N;;;;A75D;
+A75D;LATIN SMALL LETTER RUM ROTUNDA;Ll;0;L;;;;;N;;;A75C;;A75C
+A75E;LATIN CAPITAL LETTER V WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A75F;
+A75F;LATIN SMALL LETTER V WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A75E;;A75E
+A760;LATIN CAPITAL LETTER VY;Lu;0;L;;;;;N;;;;A761;
+A761;LATIN SMALL LETTER VY;Ll;0;L;;;;;N;;;A760;;A760
+A762;LATIN CAPITAL LETTER VISIGOTHIC Z;Lu;0;L;;;;;N;;;;A763;
+A763;LATIN SMALL LETTER VISIGOTHIC Z;Ll;0;L;;;;;N;;;A762;;A762
+A764;LATIN CAPITAL LETTER THORN WITH STROKE;Lu;0;L;;;;;N;;;;A765;
+A765;LATIN SMALL LETTER THORN WITH STROKE;Ll;0;L;;;;;N;;;A764;;A764
+A766;LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A767;
+A767;LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A766;;A766
+A768;LATIN CAPITAL LETTER VEND;Lu;0;L;;;;;N;;;;A769;
+A769;LATIN SMALL LETTER VEND;Ll;0;L;;;;;N;;;A768;;A768
+A76A;LATIN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;A76B;
+A76B;LATIN SMALL LETTER ET;Ll;0;L;;;;;N;;;A76A;;A76A
+A76C;LATIN CAPITAL LETTER IS;Lu;0;L;;;;;N;;;;A76D;
+A76D;LATIN SMALL LETTER IS;Ll;0;L;;;;;N;;;A76C;;A76C
+A76E;LATIN CAPITAL LETTER CON;Lu;0;L;;;;;N;;;;A76F;
+A76F;LATIN SMALL LETTER CON;Ll;0;L;;;;;N;;;A76E;;A76E
+A770;MODIFIER LETTER US;Lm;0;L;<super> A76F;;;;N;;;;;
+A771;LATIN SMALL LETTER DUM;Ll;0;L;;;;;N;;;;;
+A772;LATIN SMALL LETTER LUM;Ll;0;L;;;;;N;;;;;
+A773;LATIN SMALL LETTER MUM;Ll;0;L;;;;;N;;;;;
+A774;LATIN SMALL LETTER NUM;Ll;0;L;;;;;N;;;;;
+A775;LATIN SMALL LETTER RUM;Ll;0;L;;;;;N;;;;;
+A776;LATIN LETTER SMALL CAPITAL RUM;Ll;0;L;;;;;N;;;;;
+A777;LATIN SMALL LETTER TUM;Ll;0;L;;;;;N;;;;;
+A778;LATIN SMALL LETTER UM;Ll;0;L;;;;;N;;;;;
+A779;LATIN CAPITAL LETTER INSULAR D;Lu;0;L;;;;;N;;;;A77A;
+A77A;LATIN SMALL LETTER INSULAR D;Ll;0;L;;;;;N;;;A779;;A779
+A77B;LATIN CAPITAL LETTER INSULAR F;Lu;0;L;;;;;N;;;;A77C;
+A77C;LATIN SMALL LETTER INSULAR F;Ll;0;L;;;;;N;;;A77B;;A77B
+A77D;LATIN CAPITAL LETTER INSULAR G;Lu;0;L;;;;;N;;;;1D79;
+A77E;LATIN CAPITAL LETTER TURNED INSULAR G;Lu;0;L;;;;;N;;;;A77F;
+A77F;LATIN SMALL LETTER TURNED INSULAR G;Ll;0;L;;;;;N;;;A77E;;A77E
+A780;LATIN CAPITAL LETTER TURNED L;Lu;0;L;;;;;N;;;;A781;
+A781;LATIN SMALL LETTER TURNED L;Ll;0;L;;;;;N;;;A780;;A780
+A782;LATIN CAPITAL LETTER INSULAR R;Lu;0;L;;;;;N;;;;A783;
+A783;LATIN SMALL LETTER INSULAR R;Ll;0;L;;;;;N;;;A782;;A782
+A784;LATIN CAPITAL LETTER INSULAR S;Lu;0;L;;;;;N;;;;A785;
+A785;LATIN SMALL LETTER INSULAR S;Ll;0;L;;;;;N;;;A784;;A784
+A786;LATIN CAPITAL LETTER INSULAR T;Lu;0;L;;;;;N;;;;A787;
+A787;LATIN SMALL LETTER INSULAR T;Ll;0;L;;;;;N;;;A786;;A786
+A788;MODIFIER LETTER LOW CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;;;;;
+A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;;
+A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;;
+A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C;
+A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B
+A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;;
+A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;;
+A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;;
+A7FE;LATIN EPIGRAPHIC LETTER I LONGA;Lo;0;L;;;;;N;;;;;
+A7FF;LATIN EPIGRAPHIC LETTER ARCHAIC M;Lo;0;L;;;;;N;;;;;
+A800;SYLOTI NAGRI LETTER A;Lo;0;L;;;;;N;;;;;
+A801;SYLOTI NAGRI LETTER I;Lo;0;L;;;;;N;;;;;
+A802;SYLOTI NAGRI SIGN DVISVARA;Mn;0;NSM;;;;;N;;;;;
+A803;SYLOTI NAGRI LETTER U;Lo;0;L;;;;;N;;;;;
+A804;SYLOTI NAGRI LETTER E;Lo;0;L;;;;;N;;;;;
+A805;SYLOTI NAGRI LETTER O;Lo;0;L;;;;;N;;;;;
+A806;SYLOTI NAGRI SIGN HASANTA;Mn;9;NSM;;;;;N;;;;;
+A807;SYLOTI NAGRI LETTER KO;Lo;0;L;;;;;N;;;;;
+A808;SYLOTI NAGRI LETTER KHO;Lo;0;L;;;;;N;;;;;
+A809;SYLOTI NAGRI LETTER GO;Lo;0;L;;;;;N;;;;;
+A80A;SYLOTI NAGRI LETTER GHO;Lo;0;L;;;;;N;;;;;
+A80B;SYLOTI NAGRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+A80C;SYLOTI NAGRI LETTER CO;Lo;0;L;;;;;N;;;;;
+A80D;SYLOTI NAGRI LETTER CHO;Lo;0;L;;;;;N;;;;;
+A80E;SYLOTI NAGRI LETTER JO;Lo;0;L;;;;;N;;;;;
+A80F;SYLOTI NAGRI LETTER JHO;Lo;0;L;;;;;N;;;;;
+A810;SYLOTI NAGRI LETTER TTO;Lo;0;L;;;;;N;;;;;
+A811;SYLOTI NAGRI LETTER TTHO;Lo;0;L;;;;;N;;;;;
+A812;SYLOTI NAGRI LETTER DDO;Lo;0;L;;;;;N;;;;;
+A813;SYLOTI NAGRI LETTER DDHO;Lo;0;L;;;;;N;;;;;
+A814;SYLOTI NAGRI LETTER TO;Lo;0;L;;;;;N;;;;;
+A815;SYLOTI NAGRI LETTER THO;Lo;0;L;;;;;N;;;;;
+A816;SYLOTI NAGRI LETTER DO;Lo;0;L;;;;;N;;;;;
+A817;SYLOTI NAGRI LETTER DHO;Lo;0;L;;;;;N;;;;;
+A818;SYLOTI NAGRI LETTER NO;Lo;0;L;;;;;N;;;;;
+A819;SYLOTI NAGRI LETTER PO;Lo;0;L;;;;;N;;;;;
+A81A;SYLOTI NAGRI LETTER PHO;Lo;0;L;;;;;N;;;;;
+A81B;SYLOTI NAGRI LETTER BO;Lo;0;L;;;;;N;;;;;
+A81C;SYLOTI NAGRI LETTER BHO;Lo;0;L;;;;;N;;;;;
+A81D;SYLOTI NAGRI LETTER MO;Lo;0;L;;;;;N;;;;;
+A81E;SYLOTI NAGRI LETTER RO;Lo;0;L;;;;;N;;;;;
+A81F;SYLOTI NAGRI LETTER LO;Lo;0;L;;;;;N;;;;;
+A820;SYLOTI NAGRI LETTER RRO;Lo;0;L;;;;;N;;;;;
+A821;SYLOTI NAGRI LETTER SO;Lo;0;L;;;;;N;;;;;
+A822;SYLOTI NAGRI LETTER HO;Lo;0;L;;;;;N;;;;;
+A823;SYLOTI NAGRI VOWEL SIGN A;Mc;0;L;;;;;N;;;;;
+A824;SYLOTI NAGRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+A825;SYLOTI NAGRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+A826;SYLOTI NAGRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+A827;SYLOTI NAGRI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
+A828;SYLOTI NAGRI POETRY MARK-1;So;0;ON;;;;;N;;;;;
+A829;SYLOTI NAGRI POETRY MARK-2;So;0;ON;;;;;N;;;;;
+A82A;SYLOTI NAGRI POETRY MARK-3;So;0;ON;;;;;N;;;;;
+A82B;SYLOTI NAGRI POETRY MARK-4;So;0;ON;;;;;N;;;;;
+A830;NORTH INDIC FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;;
+A831;NORTH INDIC FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;;
+A832;NORTH INDIC FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;;
+A833;NORTH INDIC FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;;
+A834;NORTH INDIC FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;;
+A835;NORTH INDIC FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;;
+A836;NORTH INDIC QUARTER MARK;So;0;L;;;;;N;;;;;
+A837;NORTH INDIC PLACEHOLDER MARK;So;0;L;;;;;N;;;;;
+A838;NORTH INDIC RUPEE MARK;Sc;0;ET;;;;;N;;;;;
+A839;NORTH INDIC QUANTITY MARK;So;0;ET;;;;;N;;;;;
+A840;PHAGS-PA LETTER KA;Lo;0;L;;;;;N;;;;;
+A841;PHAGS-PA LETTER KHA;Lo;0;L;;;;;N;;;;;
+A842;PHAGS-PA LETTER GA;Lo;0;L;;;;;N;;;;;
+A843;PHAGS-PA LETTER NGA;Lo;0;L;;;;;N;;;;;
+A844;PHAGS-PA LETTER CA;Lo;0;L;;;;;N;;;;;
+A845;PHAGS-PA LETTER CHA;Lo;0;L;;;;;N;;;;;
+A846;PHAGS-PA LETTER JA;Lo;0;L;;;;;N;;;;;
+A847;PHAGS-PA LETTER NYA;Lo;0;L;;;;;N;;;;;
+A848;PHAGS-PA LETTER TA;Lo;0;L;;;;;N;;;;;
+A849;PHAGS-PA LETTER THA;Lo;0;L;;;;;N;;;;;
+A84A;PHAGS-PA LETTER DA;Lo;0;L;;;;;N;;;;;
+A84B;PHAGS-PA LETTER NA;Lo;0;L;;;;;N;;;;;
+A84C;PHAGS-PA LETTER PA;Lo;0;L;;;;;N;;;;;
+A84D;PHAGS-PA LETTER PHA;Lo;0;L;;;;;N;;;;;
+A84E;PHAGS-PA LETTER BA;Lo;0;L;;;;;N;;;;;
+A84F;PHAGS-PA LETTER MA;Lo;0;L;;;;;N;;;;;
+A850;PHAGS-PA LETTER TSA;Lo;0;L;;;;;N;;;;;
+A851;PHAGS-PA LETTER TSHA;Lo;0;L;;;;;N;;;;;
+A852;PHAGS-PA LETTER DZA;Lo;0;L;;;;;N;;;;;
+A853;PHAGS-PA LETTER WA;Lo;0;L;;;;;N;;;;;
+A854;PHAGS-PA LETTER ZHA;Lo;0;L;;;;;N;;;;;
+A855;PHAGS-PA LETTER ZA;Lo;0;L;;;;;N;;;;;
+A856;PHAGS-PA LETTER SMALL A;Lo;0;L;;;;;N;;;;;
+A857;PHAGS-PA LETTER YA;Lo;0;L;;;;;N;;;;;
+A858;PHAGS-PA LETTER RA;Lo;0;L;;;;;N;;;;;
+A859;PHAGS-PA LETTER LA;Lo;0;L;;;;;N;;;;;
+A85A;PHAGS-PA LETTER SHA;Lo;0;L;;;;;N;;;;;
+A85B;PHAGS-PA LETTER SA;Lo;0;L;;;;;N;;;;;
+A85C;PHAGS-PA LETTER HA;Lo;0;L;;;;;N;;;;;
+A85D;PHAGS-PA LETTER A;Lo;0;L;;;;;N;;;;;
+A85E;PHAGS-PA LETTER I;Lo;0;L;;;;;N;;;;;
+A85F;PHAGS-PA LETTER U;Lo;0;L;;;;;N;;;;;
+A860;PHAGS-PA LETTER E;Lo;0;L;;;;;N;;;;;
+A861;PHAGS-PA LETTER O;Lo;0;L;;;;;N;;;;;
+A862;PHAGS-PA LETTER QA;Lo;0;L;;;;;N;;;;;
+A863;PHAGS-PA LETTER XA;Lo;0;L;;;;;N;;;;;
+A864;PHAGS-PA LETTER FA;Lo;0;L;;;;;N;;;;;
+A865;PHAGS-PA LETTER GGA;Lo;0;L;;;;;N;;;;;
+A866;PHAGS-PA LETTER EE;Lo;0;L;;;;;N;;;;;
+A867;PHAGS-PA SUBJOINED LETTER WA;Lo;0;L;;;;;N;;;;;
+A868;PHAGS-PA SUBJOINED LETTER YA;Lo;0;L;;;;;N;;;;;
+A869;PHAGS-PA LETTER TTA;Lo;0;L;;;;;N;;;;;
+A86A;PHAGS-PA LETTER TTHA;Lo;0;L;;;;;N;;;;;
+A86B;PHAGS-PA LETTER DDA;Lo;0;L;;;;;N;;;;;
+A86C;PHAGS-PA LETTER NNA;Lo;0;L;;;;;N;;;;;
+A86D;PHAGS-PA LETTER ALTERNATE YA;Lo;0;L;;;;;N;;;;;
+A86E;PHAGS-PA LETTER VOICELESS SHA;Lo;0;L;;;;;N;;;;;
+A86F;PHAGS-PA LETTER VOICED HA;Lo;0;L;;;;;N;;;;;
+A870;PHAGS-PA LETTER ASPIRATED FA;Lo;0;L;;;;;N;;;;;
+A871;PHAGS-PA SUBJOINED LETTER RA;Lo;0;L;;;;;N;;;;;
+A872;PHAGS-PA SUPERFIXED LETTER RA;Lo;0;L;;;;;N;;;;;
+A873;PHAGS-PA LETTER CANDRABINDU;Lo;0;L;;;;;N;;;;;
+A874;PHAGS-PA SINGLE HEAD MARK;Po;0;ON;;;;;N;;;;;
+A875;PHAGS-PA DOUBLE HEAD MARK;Po;0;ON;;;;;N;;;;;
+A876;PHAGS-PA MARK SHAD;Po;0;ON;;;;;N;;;;;
+A877;PHAGS-PA MARK DOUBLE SHAD;Po;0;ON;;;;;N;;;;;
+A880;SAURASHTRA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
+A881;SAURASHTRA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+A882;SAURASHTRA LETTER A;Lo;0;L;;;;;N;;;;;
+A883;SAURASHTRA LETTER AA;Lo;0;L;;;;;N;;;;;
+A884;SAURASHTRA LETTER I;Lo;0;L;;;;;N;;;;;
+A885;SAURASHTRA LETTER II;Lo;0;L;;;;;N;;;;;
+A886;SAURASHTRA LETTER U;Lo;0;L;;;;;N;;;;;
+A887;SAURASHTRA LETTER UU;Lo;0;L;;;;;N;;;;;
+A888;SAURASHTRA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;;
+A889;SAURASHTRA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
+A88A;SAURASHTRA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;;
+A88B;SAURASHTRA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
+A88C;SAURASHTRA LETTER E;Lo;0;L;;;;;N;;;;;
+A88D;SAURASHTRA LETTER EE;Lo;0;L;;;;;N;;;;;
+A88E;SAURASHTRA LETTER AI;Lo;0;L;;;;;N;;;;;
+A88F;SAURASHTRA LETTER O;Lo;0;L;;;;;N;;;;;
+A890;SAURASHTRA LETTER OO;Lo;0;L;;;;;N;;;;;
+A891;SAURASHTRA LETTER AU;Lo;0;L;;;;;N;;;;;
+A892;SAURASHTRA LETTER KA;Lo;0;L;;;;;N;;;;;
+A893;SAURASHTRA LETTER KHA;Lo;0;L;;;;;N;;;;;
+A894;SAURASHTRA LETTER GA;Lo;0;L;;;;;N;;;;;
+A895;SAURASHTRA LETTER GHA;Lo;0;L;;;;;N;;;;;
+A896;SAURASHTRA LETTER NGA;Lo;0;L;;;;;N;;;;;
+A897;SAURASHTRA LETTER CA;Lo;0;L;;;;;N;;;;;
+A898;SAURASHTRA LETTER CHA;Lo;0;L;;;;;N;;;;;
+A899;SAURASHTRA LETTER JA;Lo;0;L;;;;;N;;;;;
+A89A;SAURASHTRA LETTER JHA;Lo;0;L;;;;;N;;;;;
+A89B;SAURASHTRA LETTER NYA;Lo;0;L;;;;;N;;;;;
+A89C;SAURASHTRA LETTER TTA;Lo;0;L;;;;;N;;;;;
+A89D;SAURASHTRA LETTER TTHA;Lo;0;L;;;;;N;;;;;
+A89E;SAURASHTRA LETTER DDA;Lo;0;L;;;;;N;;;;;
+A89F;SAURASHTRA LETTER DDHA;Lo;0;L;;;;;N;;;;;
+A8A0;SAURASHTRA LETTER NNA;Lo;0;L;;;;;N;;;;;
+A8A1;SAURASHTRA LETTER TA;Lo;0;L;;;;;N;;;;;
+A8A2;SAURASHTRA LETTER THA;Lo;0;L;;;;;N;;;;;
+A8A3;SAURASHTRA LETTER DA;Lo;0;L;;;;;N;;;;;
+A8A4;SAURASHTRA LETTER DHA;Lo;0;L;;;;;N;;;;;
+A8A5;SAURASHTRA LETTER NA;Lo;0;L;;;;;N;;;;;
+A8A6;SAURASHTRA LETTER PA;Lo;0;L;;;;;N;;;;;
+A8A7;SAURASHTRA LETTER PHA;Lo;0;L;;;;;N;;;;;
+A8A8;SAURASHTRA LETTER BA;Lo;0;L;;;;;N;;;;;
+A8A9;SAURASHTRA LETTER BHA;Lo;0;L;;;;;N;;;;;
+A8AA;SAURASHTRA LETTER MA;Lo;0;L;;;;;N;;;;;
+A8AB;SAURASHTRA LETTER YA;Lo;0;L;;;;;N;;;;;
+A8AC;SAURASHTRA LETTER RA;Lo;0;L;;;;;N;;;;;
+A8AD;SAURASHTRA LETTER LA;Lo;0;L;;;;;N;;;;;
+A8AE;SAURASHTRA LETTER VA;Lo;0;L;;;;;N;;;;;
+A8AF;SAURASHTRA LETTER SHA;Lo;0;L;;;;;N;;;;;
+A8B0;SAURASHTRA LETTER SSA;Lo;0;L;;;;;N;;;;;
+A8B1;SAURASHTRA LETTER SA;Lo;0;L;;;;;N;;;;;
+A8B2;SAURASHTRA LETTER HA;Lo;0;L;;;;;N;;;;;
+A8B3;SAURASHTRA LETTER LLA;Lo;0;L;;;;;N;;;;;
+A8B4;SAURASHTRA CONSONANT SIGN HAARU;Mc;0;L;;;;;N;;;;;
+A8B5;SAURASHTRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+A8B6;SAURASHTRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+A8B7;SAURASHTRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+A8B8;SAURASHTRA VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
+A8B9;SAURASHTRA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
+A8BA;SAURASHTRA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;;
+A8BB;SAURASHTRA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;;
+A8BC;SAURASHTRA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;;
+A8BD;SAURASHTRA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;;
+A8BE;SAURASHTRA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+A8BF;SAURASHTRA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;;
+A8C0;SAURASHTRA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;;
+A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;;
+A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;;
+A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+A8D1;SAURASHTRA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+A8D2;SAURASHTRA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+A8D3;SAURASHTRA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+A8D4;SAURASHTRA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+A8D5;SAURASHTRA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+A8D6;SAURASHTRA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+A8D7;SAURASHTRA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+A8D8;SAURASHTRA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+A8D9;SAURASHTRA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+A8E0;COMBINING DEVANAGARI DIGIT ZERO;Mn;230;NSM;;;;;N;;;;;
+A8E1;COMBINING DEVANAGARI DIGIT ONE;Mn;230;NSM;;;;;N;;;;;
+A8E2;COMBINING DEVANAGARI DIGIT TWO;Mn;230;NSM;;;;;N;;;;;
+A8E3;COMBINING DEVANAGARI DIGIT THREE;Mn;230;NSM;;;;;N;;;;;
+A8E4;COMBINING DEVANAGARI DIGIT FOUR;Mn;230;NSM;;;;;N;;;;;
+A8E5;COMBINING DEVANAGARI DIGIT FIVE;Mn;230;NSM;;;;;N;;;;;
+A8E6;COMBINING DEVANAGARI DIGIT SIX;Mn;230;NSM;;;;;N;;;;;
+A8E7;COMBINING DEVANAGARI DIGIT SEVEN;Mn;230;NSM;;;;;N;;;;;
+A8E8;COMBINING DEVANAGARI DIGIT EIGHT;Mn;230;NSM;;;;;N;;;;;
+A8E9;COMBINING DEVANAGARI DIGIT NINE;Mn;230;NSM;;;;;N;;;;;
+A8EA;COMBINING DEVANAGARI LETTER A;Mn;230;NSM;;;;;N;;;;;
+A8EB;COMBINING DEVANAGARI LETTER U;Mn;230;NSM;;;;;N;;;;;
+A8EC;COMBINING DEVANAGARI LETTER KA;Mn;230;NSM;;;;;N;;;;;
+A8ED;COMBINING DEVANAGARI LETTER NA;Mn;230;NSM;;;;;N;;;;;
+A8EE;COMBINING DEVANAGARI LETTER PA;Mn;230;NSM;;;;;N;;;;;
+A8EF;COMBINING DEVANAGARI LETTER RA;Mn;230;NSM;;;;;N;;;;;
+A8F0;COMBINING DEVANAGARI LETTER VI;Mn;230;NSM;;;;;N;;;;;
+A8F1;COMBINING DEVANAGARI SIGN AVAGRAHA;Mn;230;NSM;;;;;N;;;;;
+A8F2;DEVANAGARI SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;;
+A8F3;DEVANAGARI SIGN CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;;
+A8F4;DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;;
+A8F5;DEVANAGARI SIGN CANDRABINDU TWO;Lo;0;L;;;;;N;;;;;
+A8F6;DEVANAGARI SIGN CANDRABINDU THREE;Lo;0;L;;;;;N;;;;;
+A8F7;DEVANAGARI SIGN CANDRABINDU AVAGRAHA;Lo;0;L;;;;;N;;;;;
+A8F8;DEVANAGARI SIGN PUSHPIKA;Po;0;L;;;;;N;;;;;
+A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;;
+A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;;
+A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;;
+A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+A903;KAYAH LI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+A904;KAYAH LI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+A905;KAYAH LI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+A906;KAYAH LI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+A907;KAYAH LI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+A908;KAYAH LI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+A909;KAYAH LI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+A90A;KAYAH LI LETTER KA;Lo;0;L;;;;;N;;;;;
+A90B;KAYAH LI LETTER KHA;Lo;0;L;;;;;N;;;;;
+A90C;KAYAH LI LETTER GA;Lo;0;L;;;;;N;;;;;
+A90D;KAYAH LI LETTER NGA;Lo;0;L;;;;;N;;;;;
+A90E;KAYAH LI LETTER SA;Lo;0;L;;;;;N;;;;;
+A90F;KAYAH LI LETTER SHA;Lo;0;L;;;;;N;;;;;
+A910;KAYAH LI LETTER ZA;Lo;0;L;;;;;N;;;;;
+A911;KAYAH LI LETTER NYA;Lo;0;L;;;;;N;;;;;
+A912;KAYAH LI LETTER TA;Lo;0;L;;;;;N;;;;;
+A913;KAYAH LI LETTER HTA;Lo;0;L;;;;;N;;;;;
+A914;KAYAH LI LETTER NA;Lo;0;L;;;;;N;;;;;
+A915;KAYAH LI LETTER PA;Lo;0;L;;;;;N;;;;;
+A916;KAYAH LI LETTER PHA;Lo;0;L;;;;;N;;;;;
+A917;KAYAH LI LETTER MA;Lo;0;L;;;;;N;;;;;
+A918;KAYAH LI LETTER DA;Lo;0;L;;;;;N;;;;;
+A919;KAYAH LI LETTER BA;Lo;0;L;;;;;N;;;;;
+A91A;KAYAH LI LETTER RA;Lo;0;L;;;;;N;;;;;
+A91B;KAYAH LI LETTER YA;Lo;0;L;;;;;N;;;;;
+A91C;KAYAH LI LETTER LA;Lo;0;L;;;;;N;;;;;
+A91D;KAYAH LI LETTER WA;Lo;0;L;;;;;N;;;;;
+A91E;KAYAH LI LETTER THA;Lo;0;L;;;;;N;;;;;
+A91F;KAYAH LI LETTER HA;Lo;0;L;;;;;N;;;;;
+A920;KAYAH LI LETTER VA;Lo;0;L;;;;;N;;;;;
+A921;KAYAH LI LETTER CA;Lo;0;L;;;;;N;;;;;
+A922;KAYAH LI LETTER A;Lo;0;L;;;;;N;;;;;
+A923;KAYAH LI LETTER OE;Lo;0;L;;;;;N;;;;;
+A924;KAYAH LI LETTER I;Lo;0;L;;;;;N;;;;;
+A925;KAYAH LI LETTER OO;Lo;0;L;;;;;N;;;;;
+A926;KAYAH LI VOWEL UE;Mn;0;NSM;;;;;N;;;;;
+A927;KAYAH LI VOWEL E;Mn;0;NSM;;;;;N;;;;;
+A928;KAYAH LI VOWEL U;Mn;0;NSM;;;;;N;;;;;
+A929;KAYAH LI VOWEL EE;Mn;0;NSM;;;;;N;;;;;
+A92A;KAYAH LI VOWEL O;Mn;0;NSM;;;;;N;;;;;
+A92B;KAYAH LI TONE PLOPHU;Mn;220;NSM;;;;;N;;;;;
+A92C;KAYAH LI TONE CALYA;Mn;220;NSM;;;;;N;;;;;
+A92D;KAYAH LI TONE CALYA PLOPHU;Mn;220;NSM;;;;;N;;;;;
+A92E;KAYAH LI SIGN CWI;Po;0;L;;;;;N;;;;;
+A92F;KAYAH LI SIGN SHYA;Po;0;L;;;;;N;;;;;
+A930;REJANG LETTER KA;Lo;0;L;;;;;N;;;;;
+A931;REJANG LETTER GA;Lo;0;L;;;;;N;;;;;
+A932;REJANG LETTER NGA;Lo;0;L;;;;;N;;;;;
+A933;REJANG LETTER TA;Lo;0;L;;;;;N;;;;;
+A934;REJANG LETTER DA;Lo;0;L;;;;;N;;;;;
+A935;REJANG LETTER NA;Lo;0;L;;;;;N;;;;;
+A936;REJANG LETTER PA;Lo;0;L;;;;;N;;;;;
+A937;REJANG LETTER BA;Lo;0;L;;;;;N;;;;;
+A938;REJANG LETTER MA;Lo;0;L;;;;;N;;;;;
+A939;REJANG LETTER CA;Lo;0;L;;;;;N;;;;;
+A93A;REJANG LETTER JA;Lo;0;L;;;;;N;;;;;
+A93B;REJANG LETTER NYA;Lo;0;L;;;;;N;;;;;
+A93C;REJANG LETTER SA;Lo;0;L;;;;;N;;;;;
+A93D;REJANG LETTER RA;Lo;0;L;;;;;N;;;;;
+A93E;REJANG LETTER LA;Lo;0;L;;;;;N;;;;;
+A93F;REJANG LETTER YA;Lo;0;L;;;;;N;;;;;
+A940;REJANG LETTER WA;Lo;0;L;;;;;N;;;;;
+A941;REJANG LETTER HA;Lo;0;L;;;;;N;;;;;
+A942;REJANG LETTER MBA;Lo;0;L;;;;;N;;;;;
+A943;REJANG LETTER NGGA;Lo;0;L;;;;;N;;;;;
+A944;REJANG LETTER NDA;Lo;0;L;;;;;N;;;;;
+A945;REJANG LETTER NYJA;Lo;0;L;;;;;N;;;;;
+A946;REJANG LETTER A;Lo;0;L;;;;;N;;;;;
+A947;REJANG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+A948;REJANG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+A949;REJANG VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+A94A;REJANG VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+A94B;REJANG VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+A94C;REJANG VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
+A94D;REJANG VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;;
+A94E;REJANG VOWEL SIGN EA;Mn;0;NSM;;;;;N;;;;;
+A94F;REJANG CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;;
+A950;REJANG CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;;
+A951;REJANG CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;;
+A952;REJANG CONSONANT SIGN H;Mc;0;L;;;;;N;;;;;
+A953;REJANG VIRAMA;Mc;9;L;;;;;N;;;;;
+A95F;REJANG SECTION MARK;Po;0;L;;;;;N;;;;;
+A960;HANGUL CHOSEONG TIKEUT-MIEUM;Lo;0;L;;;;;N;;;;;
+A961;HANGUL CHOSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;;
+A962;HANGUL CHOSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;;
+A963;HANGUL CHOSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;;
+A964;HANGUL CHOSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;;
+A965;HANGUL CHOSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
+A966;HANGUL CHOSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;;
+A967;HANGUL CHOSEONG RIEUL-SSANGTIKEUT;Lo;0;L;;;;;N;;;;;
+A968;HANGUL CHOSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;;
+A969;HANGUL CHOSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;;
+A96A;HANGUL CHOSEONG RIEUL-SSANGPIEUP;Lo;0;L;;;;;N;;;;;
+A96B;HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
+A96C;HANGUL CHOSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;;
+A96D;HANGUL CHOSEONG RIEUL-CIEUC;Lo;0;L;;;;;N;;;;;
+A96E;HANGUL CHOSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;;
+A96F;HANGUL CHOSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;;
+A970;HANGUL CHOSEONG MIEUM-TIKEUT;Lo;0;L;;;;;N;;;;;
+A971;HANGUL CHOSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;;
+A972;HANGUL CHOSEONG PIEUP-SIOS-THIEUTH;Lo;0;L;;;;;N;;;;;
+A973;HANGUL CHOSEONG PIEUP-KHIEUKH;Lo;0;L;;;;;N;;;;;
+A974;HANGUL CHOSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;;
+A975;HANGUL CHOSEONG SSANGSIOS-PIEUP;Lo;0;L;;;;;N;;;;;
+A976;HANGUL CHOSEONG IEUNG-RIEUL;Lo;0;L;;;;;N;;;;;
+A977;HANGUL CHOSEONG IEUNG-HIEUH;Lo;0;L;;;;;N;;;;;
+A978;HANGUL CHOSEONG SSANGCIEUC-HIEUH;Lo;0;L;;;;;N;;;;;
+A979;HANGUL CHOSEONG SSANGTHIEUTH;Lo;0;L;;;;;N;;;;;
+A97A;HANGUL CHOSEONG PHIEUPH-HIEUH;Lo;0;L;;;;;N;;;;;
+A97B;HANGUL CHOSEONG HIEUH-SIOS;Lo;0;L;;;;;N;;;;;
+A97C;HANGUL CHOSEONG SSANGYEORINHIEUH;Lo;0;L;;;;;N;;;;;
+A980;JAVANESE SIGN PANYANGGA;Mn;0;NSM;;;;;N;;;;;
+A981;JAVANESE SIGN CECAK;Mn;0;NSM;;;;;N;;;;;
+A982;JAVANESE SIGN LAYAR;Mn;0;NSM;;;;;N;;;;;
+A983;JAVANESE SIGN WIGNYAN;Mc;0;L;;;;;N;;;;;
+A984;JAVANESE LETTER A;Lo;0;L;;;;;N;;;;;
+A985;JAVANESE LETTER I KAWI;Lo;0;L;;;;;N;;;;;
+A986;JAVANESE LETTER I;Lo;0;L;;;;;N;;;;;
+A987;JAVANESE LETTER II;Lo;0;L;;;;;N;;;;;
+A988;JAVANESE LETTER U;Lo;0;L;;;;;N;;;;;
+A989;JAVANESE LETTER PA CEREK;Lo;0;L;;;;;N;;;;;
+A98A;JAVANESE LETTER NGA LELET;Lo;0;L;;;;;N;;;;;
+A98B;JAVANESE LETTER NGA LELET RASWADI;Lo;0;L;;;;;N;;;;;
+A98C;JAVANESE LETTER E;Lo;0;L;;;;;N;;;;;
+A98D;JAVANESE LETTER AI;Lo;0;L;;;;;N;;;;;
+A98E;JAVANESE LETTER O;Lo;0;L;;;;;N;;;;;
+A98F;JAVANESE LETTER KA;Lo;0;L;;;;;N;;;;;
+A990;JAVANESE LETTER KA SASAK;Lo;0;L;;;;;N;;;;;
+A991;JAVANESE LETTER KA MURDA;Lo;0;L;;;;;N;;;;;
+A992;JAVANESE LETTER GA;Lo;0;L;;;;;N;;;;;
+A993;JAVANESE LETTER GA MURDA;Lo;0;L;;;;;N;;;;;
+A994;JAVANESE LETTER NGA;Lo;0;L;;;;;N;;;;;
+A995;JAVANESE LETTER CA;Lo;0;L;;;;;N;;;;;
+A996;JAVANESE LETTER CA MURDA;Lo;0;L;;;;;N;;;;;
+A997;JAVANESE LETTER JA;Lo;0;L;;;;;N;;;;;
+A998;JAVANESE LETTER NYA MURDA;Lo;0;L;;;;;N;;;;;
+A999;JAVANESE LETTER JA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+A99A;JAVANESE LETTER NYA;Lo;0;L;;;;;N;;;;;
+A99B;JAVANESE LETTER TTA;Lo;0;L;;;;;N;;;;;
+A99C;JAVANESE LETTER TTA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+A99D;JAVANESE LETTER DDA;Lo;0;L;;;;;N;;;;;
+A99E;JAVANESE LETTER DDA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+A99F;JAVANESE LETTER NA MURDA;Lo;0;L;;;;;N;;;;;
+A9A0;JAVANESE LETTER TA;Lo;0;L;;;;;N;;;;;
+A9A1;JAVANESE LETTER TA MURDA;Lo;0;L;;;;;N;;;;;
+A9A2;JAVANESE LETTER DA;Lo;0;L;;;;;N;;;;;
+A9A3;JAVANESE LETTER DA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+A9A4;JAVANESE LETTER NA;Lo;0;L;;;;;N;;;;;
+A9A5;JAVANESE LETTER PA;Lo;0;L;;;;;N;;;;;
+A9A6;JAVANESE LETTER PA MURDA;Lo;0;L;;;;;N;;;;;
+A9A7;JAVANESE LETTER BA;Lo;0;L;;;;;N;;;;;
+A9A8;JAVANESE LETTER BA MURDA;Lo;0;L;;;;;N;;;;;
+A9A9;JAVANESE LETTER MA;Lo;0;L;;;;;N;;;;;
+A9AA;JAVANESE LETTER YA;Lo;0;L;;;;;N;;;;;
+A9AB;JAVANESE LETTER RA;Lo;0;L;;;;;N;;;;;
+A9AC;JAVANESE LETTER RA AGUNG;Lo;0;L;;;;;N;;;;;
+A9AD;JAVANESE LETTER LA;Lo;0;L;;;;;N;;;;;
+A9AE;JAVANESE LETTER WA;Lo;0;L;;;;;N;;;;;
+A9AF;JAVANESE LETTER SA MURDA;Lo;0;L;;;;;N;;;;;
+A9B0;JAVANESE LETTER SA MAHAPRANA;Lo;0;L;;;;;N;;;;;
+A9B1;JAVANESE LETTER SA;Lo;0;L;;;;;N;;;;;
+A9B2;JAVANESE LETTER HA;Lo;0;L;;;;;N;;;;;
+A9B3;JAVANESE SIGN CECAK TELU;Mn;7;NSM;;;;;N;;;;;
+A9B4;JAVANESE VOWEL SIGN TARUNG;Mc;0;L;;;;;N;;;;;
+A9B5;JAVANESE VOWEL SIGN TOLONG;Mc;0;L;;;;;N;;;;;
+A9B6;JAVANESE VOWEL SIGN WULU;Mn;0;NSM;;;;;N;;;;;
+A9B7;JAVANESE VOWEL SIGN WULU MELIK;Mn;0;NSM;;;;;N;;;;;
+A9B8;JAVANESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;;
+A9B9;JAVANESE VOWEL SIGN SUKU MENDUT;Mn;0;NSM;;;;;N;;;;;
+A9BA;JAVANESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;;
+A9BB;JAVANESE VOWEL SIGN DIRGA MURE;Mc;0;L;;;;;N;;;;;
+A9BC;JAVANESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;;
+A9BD;JAVANESE CONSONANT SIGN KERET;Mc;0;L;;;;;N;;;;;
+A9BE;JAVANESE CONSONANT SIGN PENGKAL;Mc;0;L;;;;;N;;;;;
+A9BF;JAVANESE CONSONANT SIGN CAKRA;Mc;0;L;;;;;N;;;;;
+A9C0;JAVANESE PANGKON;Mc;9;L;;;;;N;;;;;
+A9C1;JAVANESE LEFT RERENGGAN;Po;0;L;;;;;N;;;;;
+A9C2;JAVANESE RIGHT RERENGGAN;Po;0;L;;;;;N;;;;;
+A9C3;JAVANESE PADA ANDAP;Po;0;L;;;;;N;;;;;
+A9C4;JAVANESE PADA MADYA;Po;0;L;;;;;N;;;;;
+A9C5;JAVANESE PADA LUHUR;Po;0;L;;;;;N;;;;;
+A9C6;JAVANESE PADA WINDU;Po;0;L;;;;;N;;;;;
+A9C7;JAVANESE PADA PANGKAT;Po;0;L;;;;;N;;;;;
+A9C8;JAVANESE PADA LINGSA;Po;0;L;;;;;N;;;;;
+A9C9;JAVANESE PADA LUNGSI;Po;0;L;;;;;N;;;;;
+A9CA;JAVANESE PADA ADEG;Po;0;L;;;;;N;;;;;
+A9CB;JAVANESE PADA ADEG ADEG;Po;0;L;;;;;N;;;;;
+A9CC;JAVANESE PADA PISELEH;Po;0;L;;;;;N;;;;;
+A9CD;JAVANESE TURNED PADA PISELEH;Po;0;L;;;;;N;;;;;
+A9CF;JAVANESE PANGRANGKEP;Lm;0;L;;;;;N;;;;;
+A9D0;JAVANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+A9D1;JAVANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+A9D2;JAVANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+A9D3;JAVANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+A9D4;JAVANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+A9D5;JAVANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+A9D6;JAVANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+A9D7;JAVANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+A9D8;JAVANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+A9D9;JAVANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+A9DE;JAVANESE PADA TIRTA TUMETES;Po;0;L;;;;;N;;;;;
+A9DF;JAVANESE PADA ISEN-ISEN;Po;0;L;;;;;N;;;;;
+AA00;CHAM LETTER A;Lo;0;L;;;;;N;;;;;
+AA01;CHAM LETTER I;Lo;0;L;;;;;N;;;;;
+AA02;CHAM LETTER U;Lo;0;L;;;;;N;;;;;
+AA03;CHAM LETTER E;Lo;0;L;;;;;N;;;;;
+AA04;CHAM LETTER AI;Lo;0;L;;;;;N;;;;;
+AA05;CHAM LETTER O;Lo;0;L;;;;;N;;;;;
+AA06;CHAM LETTER KA;Lo;0;L;;;;;N;;;;;
+AA07;CHAM LETTER KHA;Lo;0;L;;;;;N;;;;;
+AA08;CHAM LETTER GA;Lo;0;L;;;;;N;;;;;
+AA09;CHAM LETTER GHA;Lo;0;L;;;;;N;;;;;
+AA0A;CHAM LETTER NGUE;Lo;0;L;;;;;N;;;;;
+AA0B;CHAM LETTER NGA;Lo;0;L;;;;;N;;;;;
+AA0C;CHAM LETTER CHA;Lo;0;L;;;;;N;;;;;
+AA0D;CHAM LETTER CHHA;Lo;0;L;;;;;N;;;;;
+AA0E;CHAM LETTER JA;Lo;0;L;;;;;N;;;;;
+AA0F;CHAM LETTER JHA;Lo;0;L;;;;;N;;;;;
+AA10;CHAM LETTER NHUE;Lo;0;L;;;;;N;;;;;
+AA11;CHAM LETTER NHA;Lo;0;L;;;;;N;;;;;
+AA12;CHAM LETTER NHJA;Lo;0;L;;;;;N;;;;;
+AA13;CHAM LETTER TA;Lo;0;L;;;;;N;;;;;
+AA14;CHAM LETTER THA;Lo;0;L;;;;;N;;;;;
+AA15;CHAM LETTER DA;Lo;0;L;;;;;N;;;;;
+AA16;CHAM LETTER DHA;Lo;0;L;;;;;N;;;;;
+AA17;CHAM LETTER NUE;Lo;0;L;;;;;N;;;;;
+AA18;CHAM LETTER NA;Lo;0;L;;;;;N;;;;;
+AA19;CHAM LETTER DDA;Lo;0;L;;;;;N;;;;;
+AA1A;CHAM LETTER PA;Lo;0;L;;;;;N;;;;;
+AA1B;CHAM LETTER PPA;Lo;0;L;;;;;N;;;;;
+AA1C;CHAM LETTER PHA;Lo;0;L;;;;;N;;;;;
+AA1D;CHAM LETTER BA;Lo;0;L;;;;;N;;;;;
+AA1E;CHAM LETTER BHA;Lo;0;L;;;;;N;;;;;
+AA1F;CHAM LETTER MUE;Lo;0;L;;;;;N;;;;;
+AA20;CHAM LETTER MA;Lo;0;L;;;;;N;;;;;
+AA21;CHAM LETTER BBA;Lo;0;L;;;;;N;;;;;
+AA22;CHAM LETTER YA;Lo;0;L;;;;;N;;;;;
+AA23;CHAM LETTER RA;Lo;0;L;;;;;N;;;;;
+AA24;CHAM LETTER LA;Lo;0;L;;;;;N;;;;;
+AA25;CHAM LETTER VA;Lo;0;L;;;;;N;;;;;
+AA26;CHAM LETTER SSA;Lo;0;L;;;;;N;;;;;
+AA27;CHAM LETTER SA;Lo;0;L;;;;;N;;;;;
+AA28;CHAM LETTER HA;Lo;0;L;;;;;N;;;;;
+AA29;CHAM VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
+AA2A;CHAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+AA2B;CHAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+AA2C;CHAM VOWEL SIGN EI;Mn;0;NSM;;;;;N;;;;;
+AA2D;CHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+AA2E;CHAM VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;;
+AA2F;CHAM VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+AA30;CHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+AA31;CHAM VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
+AA32;CHAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
+AA33;CHAM CONSONANT SIGN YA;Mc;0;L;;;;;N;;;;;
+AA34;CHAM CONSONANT SIGN RA;Mc;0;L;;;;;N;;;;;
+AA35;CHAM CONSONANT SIGN LA;Mn;0;NSM;;;;;N;;;;;
+AA36;CHAM CONSONANT SIGN WA;Mn;0;NSM;;;;;N;;;;;
+AA40;CHAM LETTER FINAL K;Lo;0;L;;;;;N;;;;;
+AA41;CHAM LETTER FINAL G;Lo;0;L;;;;;N;;;;;
+AA42;CHAM LETTER FINAL NG;Lo;0;L;;;;;N;;;;;
+AA43;CHAM CONSONANT SIGN FINAL NG;Mn;0;NSM;;;;;N;;;;;
+AA44;CHAM LETTER FINAL CH;Lo;0;L;;;;;N;;;;;
+AA45;CHAM LETTER FINAL T;Lo;0;L;;;;;N;;;;;
+AA46;CHAM LETTER FINAL N;Lo;0;L;;;;;N;;;;;
+AA47;CHAM LETTER FINAL P;Lo;0;L;;;;;N;;;;;
+AA48;CHAM LETTER FINAL Y;Lo;0;L;;;;;N;;;;;
+AA49;CHAM LETTER FINAL R;Lo;0;L;;;;;N;;;;;
+AA4A;CHAM LETTER FINAL L;Lo;0;L;;;;;N;;;;;
+AA4B;CHAM LETTER FINAL SS;Lo;0;L;;;;;N;;;;;
+AA4C;CHAM CONSONANT SIGN FINAL M;Mn;0;NSM;;;;;N;;;;;
+AA4D;CHAM CONSONANT SIGN FINAL H;Mc;0;L;;;;;N;;;;;
+AA50;CHAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+AA51;CHAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+AA52;CHAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+AA53;CHAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+AA54;CHAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+AA55;CHAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+AA56;CHAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+AA57;CHAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+AA58;CHAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+AA59;CHAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+AA5C;CHAM PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;;
+AA5D;CHAM PUNCTUATION DANDA;Po;0;L;;;;;N;;;;;
+AA5E;CHAM PUNCTUATION DOUBLE DANDA;Po;0;L;;;;;N;;;;;
+AA5F;CHAM PUNCTUATION TRIPLE DANDA;Po;0;L;;;;;N;;;;;
+AA60;MYANMAR LETTER KHAMTI GA;Lo;0;L;;;;;N;;;;;
+AA61;MYANMAR LETTER KHAMTI CA;Lo;0;L;;;;;N;;;;;
+AA62;MYANMAR LETTER KHAMTI CHA;Lo;0;L;;;;;N;;;;;
+AA63;MYANMAR LETTER KHAMTI JA;Lo;0;L;;;;;N;;;;;
+AA64;MYANMAR LETTER KHAMTI JHA;Lo;0;L;;;;;N;;;;;
+AA65;MYANMAR LETTER KHAMTI NYA;Lo;0;L;;;;;N;;;;;
+AA66;MYANMAR LETTER KHAMTI TTA;Lo;0;L;;;;;N;;;;;
+AA67;MYANMAR LETTER KHAMTI TTHA;Lo;0;L;;;;;N;;;;;
+AA68;MYANMAR LETTER KHAMTI DDA;Lo;0;L;;;;;N;;;;;
+AA69;MYANMAR LETTER KHAMTI DDHA;Lo;0;L;;;;;N;;;;;
+AA6A;MYANMAR LETTER KHAMTI DHA;Lo;0;L;;;;;N;;;;;
+AA6B;MYANMAR LETTER KHAMTI NA;Lo;0;L;;;;;N;;;;;
+AA6C;MYANMAR LETTER KHAMTI SA;Lo;0;L;;;;;N;;;;;
+AA6D;MYANMAR LETTER KHAMTI HA;Lo;0;L;;;;;N;;;;;
+AA6E;MYANMAR LETTER KHAMTI HHA;Lo;0;L;;;;;N;;;;;
+AA6F;MYANMAR LETTER KHAMTI FA;Lo;0;L;;;;;N;;;;;
+AA70;MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION;Lm;0;L;;;;;N;;;;;
+AA71;MYANMAR LETTER KHAMTI XA;Lo;0;L;;;;;N;;;;;
+AA72;MYANMAR LETTER KHAMTI ZA;Lo;0;L;;;;;N;;;;;
+AA73;MYANMAR LETTER KHAMTI RA;Lo;0;L;;;;;N;;;;;
+AA74;MYANMAR LOGOGRAM KHAMTI OAY;Lo;0;L;;;;;N;;;;;
+AA75;MYANMAR LOGOGRAM KHAMTI QN;Lo;0;L;;;;;N;;;;;
+AA76;MYANMAR LOGOGRAM KHAMTI HM;Lo;0;L;;;;;N;;;;;
+AA77;MYANMAR SYMBOL AITON EXCLAMATION;So;0;L;;;;;N;;;;;
+AA78;MYANMAR SYMBOL AITON ONE;So;0;L;;;;;N;;;;;
+AA79;MYANMAR SYMBOL AITON TWO;So;0;L;;;;;N;;;;;
+AA7A;MYANMAR LETTER AITON RA;Lo;0;L;;;;;N;;;;;
+AA7B;MYANMAR SIGN PAO KAREN TONE;Mc;0;L;;;;;N;;;;;
+AA80;TAI VIET LETTER LOW KO;Lo;0;L;;;;;N;;;;;
+AA81;TAI VIET LETTER HIGH KO;Lo;0;L;;;;;N;;;;;
+AA82;TAI VIET LETTER LOW KHO;Lo;0;L;;;;;N;;;;;
+AA83;TAI VIET LETTER HIGH KHO;Lo;0;L;;;;;N;;;;;
+AA84;TAI VIET LETTER LOW KHHO;Lo;0;L;;;;;N;;;;;
+AA85;TAI VIET LETTER HIGH KHHO;Lo;0;L;;;;;N;;;;;
+AA86;TAI VIET LETTER LOW GO;Lo;0;L;;;;;N;;;;;
+AA87;TAI VIET LETTER HIGH GO;Lo;0;L;;;;;N;;;;;
+AA88;TAI VIET LETTER LOW NGO;Lo;0;L;;;;;N;;;;;
+AA89;TAI VIET LETTER HIGH NGO;Lo;0;L;;;;;N;;;;;
+AA8A;TAI VIET LETTER LOW CO;Lo;0;L;;;;;N;;;;;
+AA8B;TAI VIET LETTER HIGH CO;Lo;0;L;;;;;N;;;;;
+AA8C;TAI VIET LETTER LOW CHO;Lo;0;L;;;;;N;;;;;
+AA8D;TAI VIET LETTER HIGH CHO;Lo;0;L;;;;;N;;;;;
+AA8E;TAI VIET LETTER LOW SO;Lo;0;L;;;;;N;;;;;
+AA8F;TAI VIET LETTER HIGH SO;Lo;0;L;;;;;N;;;;;
+AA90;TAI VIET LETTER LOW NYO;Lo;0;L;;;;;N;;;;;
+AA91;TAI VIET LETTER HIGH NYO;Lo;0;L;;;;;N;;;;;
+AA92;TAI VIET LETTER LOW DO;Lo;0;L;;;;;N;;;;;
+AA93;TAI VIET LETTER HIGH DO;Lo;0;L;;;;;N;;;;;
+AA94;TAI VIET LETTER LOW TO;Lo;0;L;;;;;N;;;;;
+AA95;TAI VIET LETTER HIGH TO;Lo;0;L;;;;;N;;;;;
+AA96;TAI VIET LETTER LOW THO;Lo;0;L;;;;;N;;;;;
+AA97;TAI VIET LETTER HIGH THO;Lo;0;L;;;;;N;;;;;
+AA98;TAI VIET LETTER LOW NO;Lo;0;L;;;;;N;;;;;
+AA99;TAI VIET LETTER HIGH NO;Lo;0;L;;;;;N;;;;;
+AA9A;TAI VIET LETTER LOW BO;Lo;0;L;;;;;N;;;;;
+AA9B;TAI VIET LETTER HIGH BO;Lo;0;L;;;;;N;;;;;
+AA9C;TAI VIET LETTER LOW PO;Lo;0;L;;;;;N;;;;;
+AA9D;TAI VIET LETTER HIGH PO;Lo;0;L;;;;;N;;;;;
+AA9E;TAI VIET LETTER LOW PHO;Lo;0;L;;;;;N;;;;;
+AA9F;TAI VIET LETTER HIGH PHO;Lo;0;L;;;;;N;;;;;
+AAA0;TAI VIET LETTER LOW FO;Lo;0;L;;;;;N;;;;;
+AAA1;TAI VIET LETTER HIGH FO;Lo;0;L;;;;;N;;;;;
+AAA2;TAI VIET LETTER LOW MO;Lo;0;L;;;;;N;;;;;
+AAA3;TAI VIET LETTER HIGH MO;Lo;0;L;;;;;N;;;;;
+AAA4;TAI VIET LETTER LOW YO;Lo;0;L;;;;;N;;;;;
+AAA5;TAI VIET LETTER HIGH YO;Lo;0;L;;;;;N;;;;;
+AAA6;TAI VIET LETTER LOW RO;Lo;0;L;;;;;N;;;;;
+AAA7;TAI VIET LETTER HIGH RO;Lo;0;L;;;;;N;;;;;
+AAA8;TAI VIET LETTER LOW LO;Lo;0;L;;;;;N;;;;;
+AAA9;TAI VIET LETTER HIGH LO;Lo;0;L;;;;;N;;;;;
+AAAA;TAI VIET LETTER LOW VO;Lo;0;L;;;;;N;;;;;
+AAAB;TAI VIET LETTER HIGH VO;Lo;0;L;;;;;N;;;;;
+AAAC;TAI VIET LETTER LOW HO;Lo;0;L;;;;;N;;;;;
+AAAD;TAI VIET LETTER HIGH HO;Lo;0;L;;;;;N;;;;;
+AAAE;TAI VIET LETTER LOW O;Lo;0;L;;;;;N;;;;;
+AAAF;TAI VIET LETTER HIGH O;Lo;0;L;;;;;N;;;;;
+AAB0;TAI VIET MAI KANG;Mn;230;NSM;;;;;N;;;;;
+AAB1;TAI VIET VOWEL AA;Lo;0;L;;;;;N;;;;;
+AAB2;TAI VIET VOWEL I;Mn;230;NSM;;;;;N;;;;;
+AAB3;TAI VIET VOWEL UE;Mn;230;NSM;;;;;N;;;;;
+AAB4;TAI VIET VOWEL U;Mn;220;NSM;;;;;N;;;;;
+AAB5;TAI VIET VOWEL E;Lo;0;L;;;;;N;;;;;
+AAB6;TAI VIET VOWEL O;Lo;0;L;;;;;N;;;;;
+AAB7;TAI VIET MAI KHIT;Mn;230;NSM;;;;;N;;;;;
+AAB8;TAI VIET VOWEL IA;Mn;230;NSM;;;;;N;;;;;
+AAB9;TAI VIET VOWEL UEA;Lo;0;L;;;;;N;;;;;
+AABA;TAI VIET VOWEL UA;Lo;0;L;;;;;N;;;;;
+AABB;TAI VIET VOWEL AUE;Lo;0;L;;;;;N;;;;;
+AABC;TAI VIET VOWEL AY;Lo;0;L;;;;;N;;;;;
+AABD;TAI VIET VOWEL AN;Lo;0;L;;;;;N;;;;;
+AABE;TAI VIET VOWEL AM;Mn;230;NSM;;;;;N;;;;;
+AABF;TAI VIET TONE MAI EK;Mn;230;NSM;;;;;N;;;;;
+AAC0;TAI VIET TONE MAI NUENG;Lo;0;L;;;;;N;;;;;
+AAC1;TAI VIET TONE MAI THO;Mn;230;NSM;;;;;N;;;;;
+AAC2;TAI VIET TONE MAI SONG;Lo;0;L;;;;;N;;;;;
+AADB;TAI VIET SYMBOL KON;Lo;0;L;;;;;N;;;;;
+AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;;
+AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;;
+AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;;
+AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;;
+ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;;
+ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;;
+ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;;
+ABC3;MEETEI MAYEK LETTER MIT;Lo;0;L;;;;;N;;;;;
+ABC4;MEETEI MAYEK LETTER PA;Lo;0;L;;;;;N;;;;;
+ABC5;MEETEI MAYEK LETTER NA;Lo;0;L;;;;;N;;;;;
+ABC6;MEETEI MAYEK LETTER CHIL;Lo;0;L;;;;;N;;;;;
+ABC7;MEETEI MAYEK LETTER TIL;Lo;0;L;;;;;N;;;;;
+ABC8;MEETEI MAYEK LETTER KHOU;Lo;0;L;;;;;N;;;;;
+ABC9;MEETEI MAYEK LETTER NGOU;Lo;0;L;;;;;N;;;;;
+ABCA;MEETEI MAYEK LETTER THOU;Lo;0;L;;;;;N;;;;;
+ABCB;MEETEI MAYEK LETTER WAI;Lo;0;L;;;;;N;;;;;
+ABCC;MEETEI MAYEK LETTER YANG;Lo;0;L;;;;;N;;;;;
+ABCD;MEETEI MAYEK LETTER HUK;Lo;0;L;;;;;N;;;;;
+ABCE;MEETEI MAYEK LETTER UN;Lo;0;L;;;;;N;;;;;
+ABCF;MEETEI MAYEK LETTER I;Lo;0;L;;;;;N;;;;;
+ABD0;MEETEI MAYEK LETTER PHAM;Lo;0;L;;;;;N;;;;;
+ABD1;MEETEI MAYEK LETTER ATIYA;Lo;0;L;;;;;N;;;;;
+ABD2;MEETEI MAYEK LETTER GOK;Lo;0;L;;;;;N;;;;;
+ABD3;MEETEI MAYEK LETTER JHAM;Lo;0;L;;;;;N;;;;;
+ABD4;MEETEI MAYEK LETTER RAI;Lo;0;L;;;;;N;;;;;
+ABD5;MEETEI MAYEK LETTER BA;Lo;0;L;;;;;N;;;;;
+ABD6;MEETEI MAYEK LETTER JIL;Lo;0;L;;;;;N;;;;;
+ABD7;MEETEI MAYEK LETTER DIL;Lo;0;L;;;;;N;;;;;
+ABD8;MEETEI MAYEK LETTER GHOU;Lo;0;L;;;;;N;;;;;
+ABD9;MEETEI MAYEK LETTER DHOU;Lo;0;L;;;;;N;;;;;
+ABDA;MEETEI MAYEK LETTER BHAM;Lo;0;L;;;;;N;;;;;
+ABDB;MEETEI MAYEK LETTER KOK LONSUM;Lo;0;L;;;;;N;;;;;
+ABDC;MEETEI MAYEK LETTER LAI LONSUM;Lo;0;L;;;;;N;;;;;
+ABDD;MEETEI MAYEK LETTER MIT LONSUM;Lo;0;L;;;;;N;;;;;
+ABDE;MEETEI MAYEK LETTER PA LONSUM;Lo;0;L;;;;;N;;;;;
+ABDF;MEETEI MAYEK LETTER NA LONSUM;Lo;0;L;;;;;N;;;;;
+ABE0;MEETEI MAYEK LETTER TIL LONSUM;Lo;0;L;;;;;N;;;;;
+ABE1;MEETEI MAYEK LETTER NGOU LONSUM;Lo;0;L;;;;;N;;;;;
+ABE2;MEETEI MAYEK LETTER I LONSUM;Lo;0;L;;;;;N;;;;;
+ABE3;MEETEI MAYEK VOWEL SIGN ONAP;Mc;0;L;;;;;N;;;;;
+ABE4;MEETEI MAYEK VOWEL SIGN INAP;Mc;0;L;;;;;N;;;;;
+ABE5;MEETEI MAYEK VOWEL SIGN ANAP;Mn;0;NSM;;;;;N;;;;;
+ABE6;MEETEI MAYEK VOWEL SIGN YENAP;Mc;0;L;;;;;N;;;;;
+ABE7;MEETEI MAYEK VOWEL SIGN SOUNAP;Mc;0;L;;;;;N;;;;;
+ABE8;MEETEI MAYEK VOWEL SIGN UNAP;Mn;0;NSM;;;;;N;;;;;
+ABE9;MEETEI MAYEK VOWEL SIGN CHEINAP;Mc;0;L;;;;;N;;;;;
+ABEA;MEETEI MAYEK VOWEL SIGN NUNG;Mc;0;L;;;;;N;;;;;
+ABEB;MEETEI MAYEK CHEIKHEI;Po;0;L;;;;;N;;;;;
+ABEC;MEETEI MAYEK LUM IYEK;Mc;0;L;;;;;N;;;;;
+ABED;MEETEI MAYEK APUN IYEK;Mn;9;NSM;;;;;N;;;;;
+ABF0;MEETEI MAYEK DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+ABF1;MEETEI MAYEK DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+ABF2;MEETEI MAYEK DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+ABF3;MEETEI MAYEK DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+ABF4;MEETEI MAYEK DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+ABF5;MEETEI MAYEK DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+ABF6;MEETEI MAYEK DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+ABF7;MEETEI MAYEK DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+ABF8;MEETEI MAYEK DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+ABF9;MEETEI MAYEK DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+AC00;<Hangul Syllable, First>;Lo;0;L;;;;;N;;;;;
+D7A3;<Hangul Syllable, Last>;Lo;0;L;;;;;N;;;;;
+D7B0;HANGUL JUNGSEONG O-YEO;Lo;0;L;;;;;N;;;;;
+D7B1;HANGUL JUNGSEONG O-O-I;Lo;0;L;;;;;N;;;;;
+D7B2;HANGUL JUNGSEONG YO-A;Lo;0;L;;;;;N;;;;;
+D7B3;HANGUL JUNGSEONG YO-AE;Lo;0;L;;;;;N;;;;;
+D7B4;HANGUL JUNGSEONG YO-EO;Lo;0;L;;;;;N;;;;;
+D7B5;HANGUL JUNGSEONG U-YEO;Lo;0;L;;;;;N;;;;;
+D7B6;HANGUL JUNGSEONG U-I-I;Lo;0;L;;;;;N;;;;;
+D7B7;HANGUL JUNGSEONG YU-AE;Lo;0;L;;;;;N;;;;;
+D7B8;HANGUL JUNGSEONG YU-O;Lo;0;L;;;;;N;;;;;
+D7B9;HANGUL JUNGSEONG EU-A;Lo;0;L;;;;;N;;;;;
+D7BA;HANGUL JUNGSEONG EU-EO;Lo;0;L;;;;;N;;;;;
+D7BB;HANGUL JUNGSEONG EU-E;Lo;0;L;;;;;N;;;;;
+D7BC;HANGUL JUNGSEONG EU-O;Lo;0;L;;;;;N;;;;;
+D7BD;HANGUL JUNGSEONG I-YA-O;Lo;0;L;;;;;N;;;;;
+D7BE;HANGUL JUNGSEONG I-YAE;Lo;0;L;;;;;N;;;;;
+D7BF;HANGUL JUNGSEONG I-YEO;Lo;0;L;;;;;N;;;;;
+D7C0;HANGUL JUNGSEONG I-YE;Lo;0;L;;;;;N;;;;;
+D7C1;HANGUL JUNGSEONG I-O-I;Lo;0;L;;;;;N;;;;;
+D7C2;HANGUL JUNGSEONG I-YO;Lo;0;L;;;;;N;;;;;
+D7C3;HANGUL JUNGSEONG I-YU;Lo;0;L;;;;;N;;;;;
+D7C4;HANGUL JUNGSEONG I-I;Lo;0;L;;;;;N;;;;;
+D7C5;HANGUL JUNGSEONG ARAEA-A;Lo;0;L;;;;;N;;;;;
+D7C6;HANGUL JUNGSEONG ARAEA-E;Lo;0;L;;;;;N;;;;;
+D7CB;HANGUL JONGSEONG NIEUN-RIEUL;Lo;0;L;;;;;N;;;;;
+D7CC;HANGUL JONGSEONG NIEUN-CHIEUCH;Lo;0;L;;;;;N;;;;;
+D7CD;HANGUL JONGSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;;
+D7CE;HANGUL JONGSEONG SSANGTIKEUT-PIEUP;Lo;0;L;;;;;N;;;;;
+D7CF;HANGUL JONGSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;;
+D7D0;HANGUL JONGSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;;
+D7D1;HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
+D7D2;HANGUL JONGSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;;
+D7D3;HANGUL JONGSEONG TIKEUT-CHIEUCH;Lo;0;L;;;;;N;;;;;
+D7D4;HANGUL JONGSEONG TIKEUT-THIEUTH;Lo;0;L;;;;;N;;;;;
+D7D5;HANGUL JONGSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;;
+D7D6;HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;;
+D7D7;HANGUL JONGSEONG SSANGRIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;;
+D7D8;HANGUL JONGSEONG RIEUL-MIEUM-HIEUH;Lo;0;L;;;;;N;;;;;
+D7D9;HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;;
+D7DA;HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;;
+D7DB;HANGUL JONGSEONG RIEUL-YESIEUNG;Lo;0;L;;;;;N;;;;;
+D7DC;HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH;Lo;0;L;;;;;N;;;;;
+D7DD;HANGUL JONGSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;;
+D7DE;HANGUL JONGSEONG MIEUM-NIEUN;Lo;0;L;;;;;N;;;;;
+D7DF;HANGUL JONGSEONG MIEUM-SSANGNIEUN;Lo;0;L;;;;;N;;;;;
+D7E0;HANGUL JONGSEONG SSANGMIEUM;Lo;0;L;;;;;N;;;;;
+D7E1;HANGUL JONGSEONG MIEUM-PIEUP-SIOS;Lo;0;L;;;;;N;;;;;
+D7E2;HANGUL JONGSEONG MIEUM-CIEUC;Lo;0;L;;;;;N;;;;;
+D7E3;HANGUL JONGSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;;
+D7E4;HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;;
+D7E5;HANGUL JONGSEONG PIEUP-MIEUM;Lo;0;L;;;;;N;;;;;
+D7E6;HANGUL JONGSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;;
+D7E7;HANGUL JONGSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
+D7E8;HANGUL JONGSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;;
+D7E9;HANGUL JONGSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;;
+D7EA;HANGUL JONGSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;;
+D7EB;HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
+D7EC;HANGUL JONGSEONG SSANGSIOS-KIYEOK;Lo;0;L;;;;;N;;;;;
+D7ED;HANGUL JONGSEONG SSANGSIOS-TIKEUT;Lo;0;L;;;;;N;;;;;
+D7EE;HANGUL JONGSEONG SIOS-PANSIOS;Lo;0;L;;;;;N;;;;;
+D7EF;HANGUL JONGSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;;
+D7F0;HANGUL JONGSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;;
+D7F1;HANGUL JONGSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;;
+D7F2;HANGUL JONGSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;;
+D7F3;HANGUL JONGSEONG PANSIOS-PIEUP;Lo;0;L;;;;;N;;;;;
+D7F4;HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;;
+D7F5;HANGUL JONGSEONG YESIEUNG-MIEUM;Lo;0;L;;;;;N;;;;;
+D7F6;HANGUL JONGSEONG YESIEUNG-HIEUH;Lo;0;L;;;;;N;;;;;
+D7F7;HANGUL JONGSEONG CIEUC-PIEUP;Lo;0;L;;;;;N;;;;;
+D7F8;HANGUL JONGSEONG CIEUC-SSANGPIEUP;Lo;0;L;;;;;N;;;;;
+D7F9;HANGUL JONGSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;;
+D7FA;HANGUL JONGSEONG PHIEUPH-SIOS;Lo;0;L;;;;;N;;;;;
+D7FB;HANGUL JONGSEONG PHIEUPH-THIEUTH;Lo;0;L;;;;;N;;;;;
+D800;<Non Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;;
+DB7F;<Non Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;;
+DB80;<Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;;
+DBFF;<Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;;
+DC00;<Low Surrogate, First>;Cs;0;L;;;;;N;;;;;
+DFFF;<Low Surrogate, Last>;Cs;0;L;;;;;N;;;;;
+E000;<Private Use, First>;Co;0;L;;;;;N;;;;;
+F8FF;<Private Use, Last>;Co;0;L;;;;;N;;;;;
+F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;;
+F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;;
+F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;;
+F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;;
+F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;;
+F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;;
+F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;;
+F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;;
+F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;;
+F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;;
+F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;;
+F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;;
+F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;;
+F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;;
+F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;;
+F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;;
+F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;;
+F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;;
+F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;;
+F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;;
+F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;;
+F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;;
+F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;;
+F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;;
+F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;;
+F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;;
+F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;;
+F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;;
+F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;;
+F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;;
+F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;;
+F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;;
+F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;;
+F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;;
+F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;;
+F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;;
+F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;;
+F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;;
+F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;;
+F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;;
+F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;;
+F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;;
+F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;;
+F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;;
+F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;;
+F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;;
+F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;;
+F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;;
+F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;;
+F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;;
+F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;;
+F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;;
+F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;;
+F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;;
+F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;;
+F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;;
+F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;;
+F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;;
+F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;;
+F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;;
+F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;;
+F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;;
+F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;;
+F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;;
+F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;;
+F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;;
+F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;;
+F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;;
+F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;;
+F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;;
+F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;;
+F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;;
+F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;;
+F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;;
+F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;;
+F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;;
+F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;;
+F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;;
+F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;;
+F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;;
+F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;;
+F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;;
+F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;;
+F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;;
+F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;;
+F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;;
+F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;;
+F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;;
+F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;;
+F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;;
+F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;;
+F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;;
+F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;;
+F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;;
+F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;;
+F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;;
+F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;;
+F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;;
+F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;;
+F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;;
+F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;;
+F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;;
+F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;;
+F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;;
+F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;;
+F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;;
+F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;;
+F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;3;N;;;;;
+F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;;
+F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;;
+F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;;
+F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;;
+F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;;
+F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;;
+F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;;
+F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;10;N;;;;;
+F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;;
+F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;;
+F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;;
+F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;;
+F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;2;N;;;;;
+F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;;
+F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;;
+F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;;
+F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;;
+F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;;
+F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;;
+F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;;
+F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;;
+F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;;
+F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;;
+F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;;
+F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;;
+F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;;
+F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;;
+F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;;
+F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;;
+F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;;
+F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;;
+F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;;
+F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;;
+F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;;
+F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;;
+F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;;
+F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;;
+F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;;
+F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;;
+F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;;
+F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;;
+F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;;
+F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;;
+F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;;
+F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;;
+F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;;
+F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;;
+F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;;
+F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;;
+F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;;
+F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;;
+F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;;
+F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;;
+F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;;
+F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;;
+F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;;
+F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;;
+F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;;
+F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;;
+F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;;
+F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;;
+F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;;
+F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;;
+F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;;
+F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;;
+F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;;
+F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;;
+F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;;
+F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;;
+F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;;
+F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;0;N;;;;;
+F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;;
+F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;;
+F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;;
+F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;;
+F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;;
+F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;;
+F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;;
+F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;;
+F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;;
+F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;;
+F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;;
+F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;;
+F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;;
+F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;;
+F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;;
+F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;;
+F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;;
+F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;;
+F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;;
+F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;;
+F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;;
+F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;;
+F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;;
+F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;;
+F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;;
+F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;;
+F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;;
+F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;;
+F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;;
+F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;;
+F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;6;N;;;;;
+F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;;
+F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;6;N;;;;;
+F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;;
+F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;;
+F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;;
+F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;;
+F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;;
+F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;;
+F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;;
+F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;;
+F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;;
+F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;;
+F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;;
+F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;;
+F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;;
+F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;;
+F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;;
+F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;;
+F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;;
+F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;;
+F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;;
+F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;;
+F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;;
+F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;;
+F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;;
+F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;;
+F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;;
+F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;;
+F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;;
+F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;;
+F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;;
+F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;;
+F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;;
+F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;;
+F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;;
+F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;;
+F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;;
+F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;;
+F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;;
+F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;;
+F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;;
+F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;;
+F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;;
+F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;10;N;;;;;
+F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;;
+F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;;
+FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;;
+FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;;
+FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;;
+FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;;
+FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;;
+FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;;
+FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;;
+FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;;
+FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;;
+FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;;
+FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;;
+FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;;
+FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;;
+FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;;
+FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;;
+FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;;
+FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;;
+FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;;
+FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;;
+FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;;
+FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;;
+FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;;
+FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;;
+FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;;
+FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;;
+FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;;
+FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;;
+FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;;
+FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;;
+FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;;
+FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;;
+FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;;;;
+FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;;
+FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;;
+FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;;
+FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;;;;
+FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;;
+FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;;
+FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;;
+FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;;
+FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;;
+FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;;
+FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;;
+FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;;
+FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;;
+FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;;
+FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;;
+FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;;
+FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;;
+FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;;
+FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;;
+FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;;
+FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;;
+FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;;
+FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;;
+FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;;
+FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;;
+FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;;
+FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;;
+FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;;
+FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;;
+FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;;
+FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;;
+FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;;
+FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;;
+FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;;
+FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;;
+FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;;
+FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;;
+FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;;
+FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;;
+FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;;
+FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;;
+FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;;
+FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;;
+FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;;
+FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;;
+FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;;
+FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;;
+FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;;
+FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;;
+FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;;
+FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;;
+FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;;
+FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;;
+FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;;
+FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;;
+FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;;
+FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;;
+FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;;
+FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;;
+FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;;
+FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;;
+FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;;
+FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;;
+FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;;
+FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;;
+FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;;
+FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;;
+FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;;
+FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;;
+FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;;
+FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;;
+FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;;
+FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;;
+FA6B;CJK COMPATIBILITY IDEOGRAPH-FA6B;Lo;0;L;6075;;;;N;;;;;
+FA6C;CJK COMPATIBILITY IDEOGRAPH-FA6C;Lo;0;L;242EE;;;;N;;;;;
+FA6D;CJK COMPATIBILITY IDEOGRAPH-FA6D;Lo;0;L;8218;;;;N;;;;;
+FA70;CJK COMPATIBILITY IDEOGRAPH-FA70;Lo;0;L;4E26;;;;N;;;;;
+FA71;CJK COMPATIBILITY IDEOGRAPH-FA71;Lo;0;L;51B5;;;;N;;;;;
+FA72;CJK COMPATIBILITY IDEOGRAPH-FA72;Lo;0;L;5168;;;;N;;;;;
+FA73;CJK COMPATIBILITY IDEOGRAPH-FA73;Lo;0;L;4F80;;;;N;;;;;
+FA74;CJK COMPATIBILITY IDEOGRAPH-FA74;Lo;0;L;5145;;;;N;;;;;
+FA75;CJK COMPATIBILITY IDEOGRAPH-FA75;Lo;0;L;5180;;;;N;;;;;
+FA76;CJK COMPATIBILITY IDEOGRAPH-FA76;Lo;0;L;52C7;;;;N;;;;;
+FA77;CJK COMPATIBILITY IDEOGRAPH-FA77;Lo;0;L;52FA;;;;N;;;;;
+FA78;CJK COMPATIBILITY IDEOGRAPH-FA78;Lo;0;L;559D;;;;N;;;;;
+FA79;CJK COMPATIBILITY IDEOGRAPH-FA79;Lo;0;L;5555;;;;N;;;;;
+FA7A;CJK COMPATIBILITY IDEOGRAPH-FA7A;Lo;0;L;5599;;;;N;;;;;
+FA7B;CJK COMPATIBILITY IDEOGRAPH-FA7B;Lo;0;L;55E2;;;;N;;;;;
+FA7C;CJK COMPATIBILITY IDEOGRAPH-FA7C;Lo;0;L;585A;;;;N;;;;;
+FA7D;CJK COMPATIBILITY IDEOGRAPH-FA7D;Lo;0;L;58B3;;;;N;;;;;
+FA7E;CJK COMPATIBILITY IDEOGRAPH-FA7E;Lo;0;L;5944;;;;N;;;;;
+FA7F;CJK COMPATIBILITY IDEOGRAPH-FA7F;Lo;0;L;5954;;;;N;;;;;
+FA80;CJK COMPATIBILITY IDEOGRAPH-FA80;Lo;0;L;5A62;;;;N;;;;;
+FA81;CJK COMPATIBILITY IDEOGRAPH-FA81;Lo;0;L;5B28;;;;N;;;;;
+FA82;CJK COMPATIBILITY IDEOGRAPH-FA82;Lo;0;L;5ED2;;;;N;;;;;
+FA83;CJK COMPATIBILITY IDEOGRAPH-FA83;Lo;0;L;5ED9;;;;N;;;;;
+FA84;CJK COMPATIBILITY IDEOGRAPH-FA84;Lo;0;L;5F69;;;;N;;;;;
+FA85;CJK COMPATIBILITY IDEOGRAPH-FA85;Lo;0;L;5FAD;;;;N;;;;;
+FA86;CJK COMPATIBILITY IDEOGRAPH-FA86;Lo;0;L;60D8;;;;N;;;;;
+FA87;CJK COMPATIBILITY IDEOGRAPH-FA87;Lo;0;L;614E;;;;N;;;;;
+FA88;CJK COMPATIBILITY IDEOGRAPH-FA88;Lo;0;L;6108;;;;N;;;;;
+FA89;CJK COMPATIBILITY IDEOGRAPH-FA89;Lo;0;L;618E;;;;N;;;;;
+FA8A;CJK COMPATIBILITY IDEOGRAPH-FA8A;Lo;0;L;6160;;;;N;;;;;
+FA8B;CJK COMPATIBILITY IDEOGRAPH-FA8B;Lo;0;L;61F2;;;;N;;;;;
+FA8C;CJK COMPATIBILITY IDEOGRAPH-FA8C;Lo;0;L;6234;;;;N;;;;;
+FA8D;CJK COMPATIBILITY IDEOGRAPH-FA8D;Lo;0;L;63C4;;;;N;;;;;
+FA8E;CJK COMPATIBILITY IDEOGRAPH-FA8E;Lo;0;L;641C;;;;N;;;;;
+FA8F;CJK COMPATIBILITY IDEOGRAPH-FA8F;Lo;0;L;6452;;;;N;;;;;
+FA90;CJK COMPATIBILITY IDEOGRAPH-FA90;Lo;0;L;6556;;;;N;;;;;
+FA91;CJK COMPATIBILITY IDEOGRAPH-FA91;Lo;0;L;6674;;;;N;;;;;
+FA92;CJK COMPATIBILITY IDEOGRAPH-FA92;Lo;0;L;6717;;;;N;;;;;
+FA93;CJK COMPATIBILITY IDEOGRAPH-FA93;Lo;0;L;671B;;;;N;;;;;
+FA94;CJK COMPATIBILITY IDEOGRAPH-FA94;Lo;0;L;6756;;;;N;;;;;
+FA95;CJK COMPATIBILITY IDEOGRAPH-FA95;Lo;0;L;6B79;;;;N;;;;;
+FA96;CJK COMPATIBILITY IDEOGRAPH-FA96;Lo;0;L;6BBA;;;;N;;;;;
+FA97;CJK COMPATIBILITY IDEOGRAPH-FA97;Lo;0;L;6D41;;;;N;;;;;
+FA98;CJK COMPATIBILITY IDEOGRAPH-FA98;Lo;0;L;6EDB;;;;N;;;;;
+FA99;CJK COMPATIBILITY IDEOGRAPH-FA99;Lo;0;L;6ECB;;;;N;;;;;
+FA9A;CJK COMPATIBILITY IDEOGRAPH-FA9A;Lo;0;L;6F22;;;;N;;;;;
+FA9B;CJK COMPATIBILITY IDEOGRAPH-FA9B;Lo;0;L;701E;;;;N;;;;;
+FA9C;CJK COMPATIBILITY IDEOGRAPH-FA9C;Lo;0;L;716E;;;;N;;;;;
+FA9D;CJK COMPATIBILITY IDEOGRAPH-FA9D;Lo;0;L;77A7;;;;N;;;;;
+FA9E;CJK COMPATIBILITY IDEOGRAPH-FA9E;Lo;0;L;7235;;;;N;;;;;
+FA9F;CJK COMPATIBILITY IDEOGRAPH-FA9F;Lo;0;L;72AF;;;;N;;;;;
+FAA0;CJK COMPATIBILITY IDEOGRAPH-FAA0;Lo;0;L;732A;;;;N;;;;;
+FAA1;CJK COMPATIBILITY IDEOGRAPH-FAA1;Lo;0;L;7471;;;;N;;;;;
+FAA2;CJK COMPATIBILITY IDEOGRAPH-FAA2;Lo;0;L;7506;;;;N;;;;;
+FAA3;CJK COMPATIBILITY IDEOGRAPH-FAA3;Lo;0;L;753B;;;;N;;;;;
+FAA4;CJK COMPATIBILITY IDEOGRAPH-FAA4;Lo;0;L;761D;;;;N;;;;;
+FAA5;CJK COMPATIBILITY IDEOGRAPH-FAA5;Lo;0;L;761F;;;;N;;;;;
+FAA6;CJK COMPATIBILITY IDEOGRAPH-FAA6;Lo;0;L;76CA;;;;N;;;;;
+FAA7;CJK COMPATIBILITY IDEOGRAPH-FAA7;Lo;0;L;76DB;;;;N;;;;;
+FAA8;CJK COMPATIBILITY IDEOGRAPH-FAA8;Lo;0;L;76F4;;;;N;;;;;
+FAA9;CJK COMPATIBILITY IDEOGRAPH-FAA9;Lo;0;L;774A;;;;N;;;;;
+FAAA;CJK COMPATIBILITY IDEOGRAPH-FAAA;Lo;0;L;7740;;;;N;;;;;
+FAAB;CJK COMPATIBILITY IDEOGRAPH-FAAB;Lo;0;L;78CC;;;;N;;;;;
+FAAC;CJK COMPATIBILITY IDEOGRAPH-FAAC;Lo;0;L;7AB1;;;;N;;;;;
+FAAD;CJK COMPATIBILITY IDEOGRAPH-FAAD;Lo;0;L;7BC0;;;;N;;;;;
+FAAE;CJK COMPATIBILITY IDEOGRAPH-FAAE;Lo;0;L;7C7B;;;;N;;;;;
+FAAF;CJK COMPATIBILITY IDEOGRAPH-FAAF;Lo;0;L;7D5B;;;;N;;;;;
+FAB0;CJK COMPATIBILITY IDEOGRAPH-FAB0;Lo;0;L;7DF4;;;;N;;;;;
+FAB1;CJK COMPATIBILITY IDEOGRAPH-FAB1;Lo;0;L;7F3E;;;;N;;;;;
+FAB2;CJK COMPATIBILITY IDEOGRAPH-FAB2;Lo;0;L;8005;;;;N;;;;;
+FAB3;CJK COMPATIBILITY IDEOGRAPH-FAB3;Lo;0;L;8352;;;;N;;;;;
+FAB4;CJK COMPATIBILITY IDEOGRAPH-FAB4;Lo;0;L;83EF;;;;N;;;;;
+FAB5;CJK COMPATIBILITY IDEOGRAPH-FAB5;Lo;0;L;8779;;;;N;;;;;
+FAB6;CJK COMPATIBILITY IDEOGRAPH-FAB6;Lo;0;L;8941;;;;N;;;;;
+FAB7;CJK COMPATIBILITY IDEOGRAPH-FAB7;Lo;0;L;8986;;;;N;;;;;
+FAB8;CJK COMPATIBILITY IDEOGRAPH-FAB8;Lo;0;L;8996;;;;N;;;;;
+FAB9;CJK COMPATIBILITY IDEOGRAPH-FAB9;Lo;0;L;8ABF;;;;N;;;;;
+FABA;CJK COMPATIBILITY IDEOGRAPH-FABA;Lo;0;L;8AF8;;;;N;;;;;
+FABB;CJK COMPATIBILITY IDEOGRAPH-FABB;Lo;0;L;8ACB;;;;N;;;;;
+FABC;CJK COMPATIBILITY IDEOGRAPH-FABC;Lo;0;L;8B01;;;;N;;;;;
+FABD;CJK COMPATIBILITY IDEOGRAPH-FABD;Lo;0;L;8AFE;;;;N;;;;;
+FABE;CJK COMPATIBILITY IDEOGRAPH-FABE;Lo;0;L;8AED;;;;N;;;;;
+FABF;CJK COMPATIBILITY IDEOGRAPH-FABF;Lo;0;L;8B39;;;;N;;;;;
+FAC0;CJK COMPATIBILITY IDEOGRAPH-FAC0;Lo;0;L;8B8A;;;;N;;;;;
+FAC1;CJK COMPATIBILITY IDEOGRAPH-FAC1;Lo;0;L;8D08;;;;N;;;;;
+FAC2;CJK COMPATIBILITY IDEOGRAPH-FAC2;Lo;0;L;8F38;;;;N;;;;;
+FAC3;CJK COMPATIBILITY IDEOGRAPH-FAC3;Lo;0;L;9072;;;;N;;;;;
+FAC4;CJK COMPATIBILITY IDEOGRAPH-FAC4;Lo;0;L;9199;;;;N;;;;;
+FAC5;CJK COMPATIBILITY IDEOGRAPH-FAC5;Lo;0;L;9276;;;;N;;;;;
+FAC6;CJK COMPATIBILITY IDEOGRAPH-FAC6;Lo;0;L;967C;;;;N;;;;;
+FAC7;CJK COMPATIBILITY IDEOGRAPH-FAC7;Lo;0;L;96E3;;;;N;;;;;
+FAC8;CJK COMPATIBILITY IDEOGRAPH-FAC8;Lo;0;L;9756;;;;N;;;;;
+FAC9;CJK COMPATIBILITY IDEOGRAPH-FAC9;Lo;0;L;97DB;;;;N;;;;;
+FACA;CJK COMPATIBILITY IDEOGRAPH-FACA;Lo;0;L;97FF;;;;N;;;;;
+FACB;CJK COMPATIBILITY IDEOGRAPH-FACB;Lo;0;L;980B;;;;N;;;;;
+FACC;CJK COMPATIBILITY IDEOGRAPH-FACC;Lo;0;L;983B;;;;N;;;;;
+FACD;CJK COMPATIBILITY IDEOGRAPH-FACD;Lo;0;L;9B12;;;;N;;;;;
+FACE;CJK COMPATIBILITY IDEOGRAPH-FACE;Lo;0;L;9F9C;;;;N;;;;;
+FACF;CJK COMPATIBILITY IDEOGRAPH-FACF;Lo;0;L;2284A;;;;N;;;;;
+FAD0;CJK COMPATIBILITY IDEOGRAPH-FAD0;Lo;0;L;22844;;;;N;;;;;
+FAD1;CJK COMPATIBILITY IDEOGRAPH-FAD1;Lo;0;L;233D5;;;;N;;;;;
+FAD2;CJK COMPATIBILITY IDEOGRAPH-FAD2;Lo;0;L;3B9D;;;;N;;;;;
+FAD3;CJK COMPATIBILITY IDEOGRAPH-FAD3;Lo;0;L;4018;;;;N;;;;;
+FAD4;CJK COMPATIBILITY IDEOGRAPH-FAD4;Lo;0;L;4039;;;;N;;;;;
+FAD5;CJK COMPATIBILITY IDEOGRAPH-FAD5;Lo;0;L;25249;;;;N;;;;;
+FAD6;CJK COMPATIBILITY IDEOGRAPH-FAD6;Lo;0;L;25CD0;;;;N;;;;;
+FAD7;CJK COMPATIBILITY IDEOGRAPH-FAD7;Lo;0;L;27ED3;;;;N;;;;;
+FAD8;CJK COMPATIBILITY IDEOGRAPH-FAD8;Lo;0;L;9F43;;;;N;;;;;
+FAD9;CJK COMPATIBILITY IDEOGRAPH-FAD9;Lo;0;L;9F8E;;;;N;;;;;
+FB00;LATIN SMALL LIGATURE FF;Ll;0;L;<compat> 0066 0066;;;;N;;;;;
+FB01;LATIN SMALL LIGATURE FI;Ll;0;L;<compat> 0066 0069;;;;N;;;;;
+FB02;LATIN SMALL LIGATURE FL;Ll;0;L;<compat> 0066 006C;;;;N;;;;;
+FB03;LATIN SMALL LIGATURE FFI;Ll;0;L;<compat> 0066 0066 0069;;;;N;;;;;
+FB04;LATIN SMALL LIGATURE FFL;Ll;0;L;<compat> 0066 0066 006C;;;;N;;;;;
+FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L;<compat> 017F 0074;;;;N;;;;;
+FB06;LATIN SMALL LIGATURE ST;Ll;0;L;<compat> 0073 0074;;;;N;;;;;
+FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L;<compat> 0574 0576;;;;N;;;;;
+FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L;<compat> 0574 0565;;;;N;;;;;
+FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L;<compat> 0574 056B;;;;N;;;;;
+FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L;<compat> 057E 0576;;;;N;;;;;
+FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L;<compat> 0574 056D;;;;N;;;;;
+FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;;
+FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;;
+FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;;
+FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R;<font> 05E2;;;;N;;;;;
+FB21;HEBREW LETTER WIDE ALEF;Lo;0;R;<font> 05D0;;;;N;;;;;
+FB22;HEBREW LETTER WIDE DALET;Lo;0;R;<font> 05D3;;;;N;;;;;
+FB23;HEBREW LETTER WIDE HE;Lo;0;R;<font> 05D4;;;;N;;;;;
+FB24;HEBREW LETTER WIDE KAF;Lo;0;R;<font> 05DB;;;;N;;;;;
+FB25;HEBREW LETTER WIDE LAMED;Lo;0;R;<font> 05DC;;;;N;;;;;
+FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R;<font> 05DD;;;;N;;;;;
+FB27;HEBREW LETTER WIDE RESH;Lo;0;R;<font> 05E8;;;;N;;;;;
+FB28;HEBREW LETTER WIDE TAV;Lo;0;R;<font> 05EA;;;;N;;;;;
+FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ES;<font> 002B;;;;N;;;;;
+FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;;
+FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;;
+FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;;
+FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;;
+FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;;
+FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;;
+FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;;
+FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;;
+FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;;
+FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;;
+FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;;
+FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;;
+FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;;
+FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;;
+FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;;
+FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;;
+FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;;
+FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;;
+FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;;
+FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;;
+FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;;
+FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;;
+FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;;
+FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;;
+FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;;
+FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;;
+FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;;
+FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;;
+FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;;
+FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;;
+FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;;
+FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;;
+FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R;<compat> 05D0 05DC;;;;N;;;;;
+FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL;<isolated> 0671;;;;N;;;;;
+FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL;<final> 0671;;;;N;;;;;
+FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL;<isolated> 067B;;;;N;;;;;
+FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL;<final> 067B;;;;N;;;;;
+FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL;<initial> 067B;;;;N;;;;;
+FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL;<medial> 067B;;;;N;;;;;
+FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL;<isolated> 067E;;;;N;;;;;
+FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL;<final> 067E;;;;N;;;;;
+FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL;<initial> 067E;;;;N;;;;;
+FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL;<medial> 067E;;;;N;;;;;
+FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0680;;;;N;;;;;
+FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL;<final> 0680;;;;N;;;;;
+FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL;<initial> 0680;;;;N;;;;;
+FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL;<medial> 0680;;;;N;;;;;
+FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067A;;;;N;;;;;
+FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL;<final> 067A;;;;N;;;;;
+FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL;<initial> 067A;;;;N;;;;;
+FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL;<medial> 067A;;;;N;;;;;
+FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067F;;;;N;;;;;
+FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL;<final> 067F;;;;N;;;;;
+FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL;<initial> 067F;;;;N;;;;;
+FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL;<medial> 067F;;;;N;;;;;
+FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL;<isolated> 0679;;;;N;;;;;
+FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL;<final> 0679;;;;N;;;;;
+FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL;<initial> 0679;;;;N;;;;;
+FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL;<medial> 0679;;;;N;;;;;
+FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL;<isolated> 06A4;;;;N;;;;;
+FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL;<final> 06A4;;;;N;;;;;
+FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL;<initial> 06A4;;;;N;;;;;
+FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL;<medial> 06A4;;;;N;;;;;
+FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A6;;;;N;;;;;
+FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL;<final> 06A6;;;;N;;;;;
+FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL;<initial> 06A6;;;;N;;;;;
+FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A6;;;;N;;;;;
+FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL;<isolated> 0684;;;;N;;;;;
+FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL;<final> 0684;;;;N;;;;;
+FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL;<initial> 0684;;;;N;;;;;
+FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL;<medial> 0684;;;;N;;;;;
+FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL;<isolated> 0683;;;;N;;;;;
+FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL;<final> 0683;;;;N;;;;;
+FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL;<initial> 0683;;;;N;;;;;
+FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL;<medial> 0683;;;;N;;;;;
+FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL;<isolated> 0686;;;;N;;;;;
+FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL;<final> 0686;;;;N;;;;;
+FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL;<initial> 0686;;;;N;;;;;
+FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL;<medial> 0686;;;;N;;;;;
+FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0687;;;;N;;;;;
+FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL;<final> 0687;;;;N;;;;;
+FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL;<initial> 0687;;;;N;;;;;
+FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL;<medial> 0687;;;;N;;;;;
+FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068D;;;;N;;;;;
+FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL;<final> 068D;;;;N;;;;;
+FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068C;;;;N;;;;;
+FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL;<final> 068C;;;;N;;;;;
+FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL;<isolated> 068E;;;;N;;;;;
+FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL;<final> 068E;;;;N;;;;;
+FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL;<isolated> 0688;;;;N;;;;;
+FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL;<final> 0688;;;;N;;;;;
+FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL;<isolated> 0698;;;;N;;;;;
+FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL;<final> 0698;;;;N;;;;;
+FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL;<isolated> 0691;;;;N;;;;;
+FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL;<final> 0691;;;;N;;;;;
+FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A9;;;;N;;;;;
+FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL;<final> 06A9;;;;N;;;;;
+FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL;<initial> 06A9;;;;N;;;;;
+FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A9;;;;N;;;;;
+FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL;<isolated> 06AF;;;;N;;;;;
+FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL;<final> 06AF;;;;N;;;;;
+FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL;<initial> 06AF;;;;N;;;;;
+FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL;<medial> 06AF;;;;N;;;;;
+FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL;<isolated> 06B3;;;;N;;;;;
+FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL;<final> 06B3;;;;N;;;;;
+FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL;<initial> 06B3;;;;N;;;;;
+FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL;<medial> 06B3;;;;N;;;;;
+FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL;<isolated> 06B1;;;;N;;;;;
+FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL;<final> 06B1;;;;N;;;;;
+FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL;<initial> 06B1;;;;N;;;;;
+FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL;<medial> 06B1;;;;N;;;;;
+FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL;<isolated> 06BA;;;;N;;;;;
+FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL;<final> 06BA;;;;N;;;;;
+FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL;<isolated> 06BB;;;;N;;;;;
+FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL;<final> 06BB;;;;N;;;;;
+FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL;<initial> 06BB;;;;N;;;;;
+FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL;<medial> 06BB;;;;N;;;;;
+FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06C0;;;;N;;;;;
+FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL;<final> 06C0;;;;N;;;;;
+FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL;<isolated> 06C1;;;;N;;;;;
+FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL;<final> 06C1;;;;N;;;;;
+FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL;<initial> 06C1;;;;N;;;;;
+FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL;<medial> 06C1;;;;N;;;;;
+FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL;<isolated> 06BE;;;;N;;;;;
+FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL;<final> 06BE;;;;N;;;;;
+FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL;<initial> 06BE;;;;N;;;;;
+FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL;<medial> 06BE;;;;N;;;;;
+FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL;<isolated> 06D2;;;;N;;;;;
+FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL;<final> 06D2;;;;N;;;;;
+FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06D3;;;;N;;;;;
+FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 06D3;;;;N;;;;;
+FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL;<isolated> 06AD;;;;N;;;;;
+FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL;<final> 06AD;;;;N;;;;;
+FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL;<initial> 06AD;;;;N;;;;;
+FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL;<medial> 06AD;;;;N;;;;;
+FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL;<isolated> 06C7;;;;N;;;;;
+FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL;<final> 06C7;;;;N;;;;;
+FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL;<isolated> 06C6;;;;N;;;;;
+FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL;<final> 06C6;;;;N;;;;;
+FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL;<isolated> 06C8;;;;N;;;;;
+FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL;<final> 06C8;;;;N;;;;;
+FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0677;;;;N;;;;;
+FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL;<isolated> 06CB;;;;N;;;;;
+FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL;<final> 06CB;;;;N;;;;;
+FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL;<isolated> 06C5;;;;N;;;;;
+FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL;<final> 06C5;;;;N;;;;;
+FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL;<isolated> 06C9;;;;N;;;;;
+FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL;<final> 06C9;;;;N;;;;;
+FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL;<isolated> 06D0;;;;N;;;;;
+FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL;<final> 06D0;;;;N;;;;;
+FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL;<initial> 06D0;;;;N;;;;;
+FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL;<medial> 06D0;;;;N;;;;;
+FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0649;;;;N;;;;;
+FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL;<medial> 0649;;;;N;;;;;
+FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0626 0627;;;;N;;;;;
+FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL;<final> 0626 0627;;;;N;;;;;
+FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D5;;;;N;;;;;
+FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL;<final> 0626 06D5;;;;N;;;;;
+FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL;<isolated> 0626 0648;;;;N;;;;;
+FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL;<final> 0626 0648;;;;N;;;;;
+FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C7;;;;N;;;;;
+FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL;<final> 0626 06C7;;;;N;;;;;
+FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C6;;;;N;;;;;
+FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL;<final> 0626 06C6;;;;N;;;;;
+FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C8;;;;N;;;;;
+FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL;<final> 0626 06C8;;;;N;;;;;
+FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D0;;;;N;;;;;
+FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL;<final> 0626 06D0;;;;N;;;;;
+FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL;<initial> 0626 06D0;;;;N;;;;;
+FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;;
+FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;;
+FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0626 0649;;;;N;;;;;
+FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL;<isolated> 06CC;;;;N;;;;;
+FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL;<final> 06CC;;;;N;;;;;
+FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL;<initial> 06CC;;;;N;;;;;
+FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL;<medial> 06CC;;;;N;;;;;
+FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 062C;;;;N;;;;;
+FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0626 062D;;;;N;;;;;
+FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 0645;;;;N;;;;;
+FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;;
+FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0626 064A;;;;N;;;;;
+FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 062C;;;;N;;;;;
+FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062D;;;;N;;;;;
+FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062E;;;;N;;;;;
+FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 0645;;;;N;;;;;
+FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0628 0649;;;;N;;;;;
+FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0628 064A;;;;N;;;;;
+FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 062C;;;;N;;;;;
+FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062D;;;;N;;;;;
+FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062E;;;;N;;;;;
+FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 0645;;;;N;;;;;
+FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062A 0649;;;;N;;;;;
+FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062A 064A;;;;N;;;;;
+FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 062C;;;;N;;;;;
+FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 0645;;;;N;;;;;
+FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062B 0649;;;;N;;;;;
+FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062B 064A;;;;N;;;;;
+FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062C 062D;;;;N;;;;;
+FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C 0645;;;;N;;;;;
+FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 062C;;;;N;;;;;
+FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 0645;;;;N;;;;;
+FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 062C;;;;N;;;;;
+FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062E 062D;;;;N;;;;;
+FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 0645;;;;N;;;;;
+FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 062C;;;;N;;;;;
+FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062D;;;;N;;;;;
+FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062E;;;;N;;;;;
+FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 0645;;;;N;;;;;
+FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0635 062D;;;;N;;;;;
+FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0645;;;;N;;;;;
+FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 062C;;;;N;;;;;
+FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062D;;;;N;;;;;
+FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062E;;;;N;;;;;
+FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 0645;;;;N;;;;;
+FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0637 062D;;;;N;;;;;
+FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0637 0645;;;;N;;;;;
+FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0638 0645;;;;N;;;;;
+FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 062C;;;;N;;;;;
+FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 0645;;;;N;;;;;
+FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 062C;;;;N;;;;;
+FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 0645;;;;N;;;;;
+FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 062C;;;;N;;;;;
+FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062D;;;;N;;;;;
+FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062E;;;;N;;;;;
+FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 0645;;;;N;;;;;
+FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0641 0649;;;;N;;;;;
+FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0641 064A;;;;N;;;;;
+FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0642 062D;;;;N;;;;;
+FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0642 0645;;;;N;;;;;
+FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0642 0649;;;;N;;;;;
+FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0642 064A;;;;N;;;;;
+FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0643 0627;;;;N;;;;;
+FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 062C;;;;N;;;;;
+FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062D;;;;N;;;;;
+FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062E;;;;N;;;;;
+FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0644;;;;N;;;;;
+FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0645;;;;N;;;;;
+FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0643 0649;;;;N;;;;;
+FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0643 064A;;;;N;;;;;
+FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 062C;;;;N;;;;;
+FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062D;;;;N;;;;;
+FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062E;;;;N;;;;;
+FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 0645;;;;N;;;;;
+FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0644 0649;;;;N;;;;;
+FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0644 064A;;;;N;;;;;
+FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 062C;;;;N;;;;;
+FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D;;;;N;;;;;
+FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062E;;;;N;;;;;
+FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 0645;;;;N;;;;;
+FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0645 0649;;;;N;;;;;
+FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0645 064A;;;;N;;;;;
+FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 062C;;;;N;;;;;
+FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062D;;;;N;;;;;
+FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062E;;;;N;;;;;
+FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 0645;;;;N;;;;;
+FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0646 0649;;;;N;;;;;
+FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0646 064A;;;;N;;;;;
+FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 062C;;;;N;;;;;
+FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 0645;;;;N;;;;;
+FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0647 0649;;;;N;;;;;
+FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0647 064A;;;;N;;;;;
+FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 062C;;;;N;;;;;
+FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062D;;;;N;;;;;
+FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062E;;;;N;;;;;
+FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 0645;;;;N;;;;;
+FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 064A 0649;;;;N;;;;;
+FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A 064A;;;;N;;;;;
+FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0630 0670;;;;N;;;;;
+FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0631 0670;;;;N;;;;;
+FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0649 0670;;;;N;;;;;
+FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C 0651;;;;N;;;;;
+FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D 0651;;;;N;;;;;
+FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E 0651;;;;N;;;;;
+FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F 0651;;;;N;;;;;
+FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650 0651;;;;N;;;;;
+FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651 0670;;;;N;;;;;
+FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL;<final> 0626 0631;;;;N;;;;;
+FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0626 0632;;;;N;;;;;
+FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL;<final> 0626 0645;;;;N;;;;;
+FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL;<final> 0626 0646;;;;N;;;;;
+FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;;
+FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL;<final> 0626 064A;;;;N;;;;;
+FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL;<final> 0628 0631;;;;N;;;;;
+FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0628 0632;;;;N;;;;;
+FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0628 0645;;;;N;;;;;
+FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL;<final> 0628 0646;;;;N;;;;;
+FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0628 0649;;;;N;;;;;
+FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 064A;;;;N;;;;;
+FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL;<final> 062A 0631;;;;N;;;;;
+FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062A 0632;;;;N;;;;;
+FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062A 0645;;;;N;;;;;
+FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062A 0646;;;;N;;;;;
+FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0649;;;;N;;;;;
+FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 064A;;;;N;;;;;
+FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL;<final> 062B 0631;;;;N;;;;;
+FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062B 0632;;;;N;;;;;
+FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062B 0645;;;;N;;;;;
+FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062B 0646;;;;N;;;;;
+FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062B 0649;;;;N;;;;;
+FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062B 064A;;;;N;;;;;
+FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0641 0649;;;;N;;;;;
+FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 064A;;;;N;;;;;
+FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0642 0649;;;;N;;;;;
+FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 064A;;;;N;;;;;
+FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL;<final> 0643 0627;;;;N;;;;;
+FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL;<final> 0643 0644;;;;N;;;;;
+FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645;;;;N;;;;;
+FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0643 0649;;;;N;;;;;
+FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 064A;;;;N;;;;;
+FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 0645;;;;N;;;;;
+FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 0649;;;;N;;;;;
+FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 064A;;;;N;;;;;
+FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0645 0627;;;;N;;;;;
+FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0645 0645;;;;N;;;;;
+FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL;<final> 0646 0631;;;;N;;;;;
+FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0646 0632;;;;N;;;;;
+FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 0645;;;;N;;;;;
+FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL;<final> 0646 0646;;;;N;;;;;
+FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0649;;;;N;;;;;
+FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 064A;;;;N;;;;;
+FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL;<final> 0649 0670;;;;N;;;;;
+FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL;<final> 064A 0631;;;;N;;;;;
+FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 064A 0632;;;;N;;;;;
+FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645;;;;N;;;;;
+FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL;<final> 064A 0646;;;;N;;;;;
+FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 064A 0649;;;;N;;;;;
+FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 064A;;;;N;;;;;
+FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0626 062C;;;;N;;;;;
+FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0626 062D;;;;N;;;;;
+FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0626 062E;;;;N;;;;;
+FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0626 0645;;;;N;;;;;
+FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0626 0647;;;;N;;;;;
+FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0628 062C;;;;N;;;;;
+FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0628 062D;;;;N;;;;;
+FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0628 062E;;;;N;;;;;
+FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0628 0645;;;;N;;;;;
+FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0628 0647;;;;N;;;;;
+FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C;;;;N;;;;;
+FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 062D;;;;N;;;;;
+FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 062E;;;;N;;;;;
+FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645;;;;N;;;;;
+FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 062A 0647;;;;N;;;;;
+FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062B 0645;;;;N;;;;;
+FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 062D;;;;N;;;;;
+FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062C 0645;;;;N;;;;;
+FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062D 062C;;;;N;;;;;
+FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062D 0645;;;;N;;;;;
+FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062E 062C;;;;N;;;;;
+FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062E 0645;;;;N;;;;;
+FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062C;;;;N;;;;;
+FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062D;;;;N;;;;;
+FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0633 062E;;;;N;;;;;
+FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645;;;;N;;;;;
+FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D;;;;N;;;;;
+FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0635 062E;;;;N;;;;;
+FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645;;;;N;;;;;
+FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062C;;;;N;;;;;
+FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0636 062D;;;;N;;;;;
+FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0636 062E;;;;N;;;;;
+FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 0645;;;;N;;;;;
+FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 062D;;;;N;;;;;
+FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0638 0645;;;;N;;;;;
+FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C;;;;N;;;;;
+FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645;;;;N;;;;;
+FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 063A 062C;;;;N;;;;;
+FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 063A 0645;;;;N;;;;;
+FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062C;;;;N;;;;;
+FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0641 062D;;;;N;;;;;
+FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0641 062E;;;;N;;;;;
+FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 0645;;;;N;;;;;
+FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 062D;;;;N;;;;;
+FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0642 0645;;;;N;;;;;
+FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0643 062C;;;;N;;;;;
+FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0643 062D;;;;N;;;;;
+FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0643 062E;;;;N;;;;;
+FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL;<initial> 0643 0644;;;;N;;;;;
+FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645;;;;N;;;;;
+FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C;;;;N;;;;;
+FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 062D;;;;N;;;;;
+FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0644 062E;;;;N;;;;;
+FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 0645;;;;N;;;;;
+FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0644 0647;;;;N;;;;;
+FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C;;;;N;;;;;
+FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062D;;;;N;;;;;
+FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062E;;;;N;;;;;
+FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 0645;;;;N;;;;;
+FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C;;;;N;;;;;
+FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062D;;;;N;;;;;
+FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0646 062E;;;;N;;;;;
+FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 0645;;;;N;;;;;
+FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0646 0647;;;;N;;;;;
+FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 062C;;;;N;;;;;
+FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645;;;;N;;;;;
+FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL;<initial> 0647 0670;;;;N;;;;;
+FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 064A 062C;;;;N;;;;;
+FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 064A 062D;;;;N;;;;;
+FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 064A 062E;;;;N;;;;;
+FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645;;;;N;;;;;
+FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 064A 0647;;;;N;;;;;
+FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0626 0645;;;;N;;;;;
+FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0626 0647;;;;N;;;;;
+FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0628 0645;;;;N;;;;;
+FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0628 0647;;;;N;;;;;
+FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062A 0645;;;;N;;;;;
+FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062A 0647;;;;N;;;;;
+FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062B 0645;;;;N;;;;;
+FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062B 0647;;;;N;;;;;
+FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 0645;;;;N;;;;;
+FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0633 0647;;;;N;;;;;
+FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 0645;;;;N;;;;;
+FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0634 0647;;;;N;;;;;
+FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL;<medial> 0643 0644;;;;N;;;;;
+FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0643 0645;;;;N;;;;;
+FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0644 0645;;;;N;;;;;
+FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0646 0645;;;;N;;;;;
+FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0646 0647;;;;N;;;;;
+FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 064A 0645;;;;N;;;;;
+FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 064A 0647;;;;N;;;;;
+FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E 0651;;;;N;;;;;
+FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F 0651;;;;N;;;;;
+FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650 0651;;;;N;;;;;
+FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0637 0649;;;;N;;;;;
+FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0637 064A;;;;N;;;;;
+FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0639 0649;;;;N;;;;;
+FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0639 064A;;;;N;;;;;
+FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 063A 0649;;;;N;;;;;
+FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 063A 064A;;;;N;;;;;
+FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0633 0649;;;;N;;;;;
+FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0633 064A;;;;N;;;;;
+FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0634 0649;;;;N;;;;;
+FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0634 064A;;;;N;;;;;
+FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062D 0649;;;;N;;;;;
+FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062D 064A;;;;N;;;;;
+FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062C 0649;;;;N;;;;;
+FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062C 064A;;;;N;;;;;
+FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062E 0649;;;;N;;;;;
+FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062E 064A;;;;N;;;;;
+FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0649;;;;N;;;;;
+FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0635 064A;;;;N;;;;;
+FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0636 0649;;;;N;;;;;
+FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0636 064A;;;;N;;;;;
+FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 062C;;;;N;;;;;
+FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062D;;;;N;;;;;
+FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062E;;;;N;;;;;
+FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 0645;;;;N;;;;;
+FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0634 0631;;;;N;;;;;
+FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0633 0631;;;;N;;;;;
+FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0635 0631;;;;N;;;;;
+FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0636 0631;;;;N;;;;;
+FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0637 0649;;;;N;;;;;
+FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 064A;;;;N;;;;;
+FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0649;;;;N;;;;;
+FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 064A;;;;N;;;;;
+FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0649;;;;N;;;;;
+FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 064A;;;;N;;;;;
+FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 0649;;;;N;;;;;
+FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 064A;;;;N;;;;;
+FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0634 0649;;;;N;;;;;
+FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 064A;;;;N;;;;;
+FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0649;;;;N;;;;;
+FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 064A;;;;N;;;;;
+FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0649;;;;N;;;;;
+FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 064A;;;;N;;;;;
+FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062E 0649;;;;N;;;;;
+FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062E 064A;;;;N;;;;;
+FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0635 0649;;;;N;;;;;
+FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 064A;;;;N;;;;;
+FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 0649;;;;N;;;;;
+FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 064A;;;;N;;;;;
+FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL;<final> 0634 062C;;;;N;;;;;
+FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL;<final> 0634 062D;;;;N;;;;;
+FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 062E;;;;N;;;;;
+FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645;;;;N;;;;;
+FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0634 0631;;;;N;;;;;
+FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0633 0631;;;;N;;;;;
+FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL;<final> 0635 0631;;;;N;;;;;
+FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL;<final> 0636 0631;;;;N;;;;;
+FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062C;;;;N;;;;;
+FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0634 062D;;;;N;;;;;
+FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 062E;;;;N;;;;;
+FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645;;;;N;;;;;
+FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0633 0647;;;;N;;;;;
+FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0634 0647;;;;N;;;;;
+FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645;;;;N;;;;;
+FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 062C;;;;N;;;;;
+FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062D;;;;N;;;;;
+FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062E;;;;N;;;;;
+FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 062C;;;;N;;;;;
+FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062D;;;;N;;;;;
+FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062E;;;;N;;;;;
+FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0637 0645;;;;N;;;;;
+FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0638 0645;;;;N;;;;;
+FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL;<final> 0627 064B;;;;N;;;;;
+FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0627 064B;;;;N;;;;;
+FD3E;ORNATE LEFT PARENTHESIS;Ps;0;ON;;;;;N;;;;;
+FD3F;ORNATE RIGHT PARENTHESIS;Pe;0;ON;;;;;N;;;;;
+FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C 0645;;;;N;;;;;
+FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL;<final> 062A 062D 062C;;;;N;;;;;
+FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 062C;;;;N;;;;;
+FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 0645;;;;N;;;;;
+FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062E 0645;;;;N;;;;;
+FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062C;;;;N;;;;;
+FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062D;;;;N;;;;;
+FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062E;;;;N;;;;;
+FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 062C 0645 062D;;;;N;;;;;
+FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 0645 062D;;;;N;;;;;
+FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 0645 064A;;;;N;;;;;
+FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0645 0649;;;;N;;;;;
+FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062D 062C;;;;N;;;;;
+FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062C 062D;;;;N;;;;;
+FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062C 0649;;;;N;;;;;
+FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0633 0645 062D;;;;N;;;;;
+FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062D;;;;N;;;;;
+FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062C;;;;N;;;;;
+FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0633 0645 0645;;;;N;;;;;
+FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 0645;;;;N;;;;;
+FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL;<final> 0635 062D 062D;;;;N;;;;;
+FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D 062D;;;;N;;;;;
+FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0635 0645 0645;;;;N;;;;;
+FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 062D 0645;;;;N;;;;;
+FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062D 0645;;;;N;;;;;
+FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062C 064A;;;;N;;;;;
+FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 0645 062E;;;;N;;;;;
+FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 0645 062E;;;;N;;;;;
+FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645 0645;;;;N;;;;;
+FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645 0645;;;;N;;;;;
+FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 062D 0649;;;;N;;;;;
+FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0636 062E 0645;;;;N;;;;;
+FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062E 0645;;;;N;;;;;
+FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0637 0645 062D;;;;N;;;;;
+FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 0645 062D;;;;N;;;;;
+FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645 0645;;;;N;;;;;
+FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 0645 064A;;;;N;;;;;
+FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 062C 0645;;;;N;;;;;
+FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 0645 0645;;;;N;;;;;
+FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645 0645;;;;N;;;;;
+FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0645 0649;;;;N;;;;;
+FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 063A 0645 0645;;;;N;;;;;
+FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 0645 064A;;;;N;;;;;
+FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0645 0649;;;;N;;;;;
+FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0641 062E 0645;;;;N;;;;;
+FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062E 0645;;;;N;;;;;
+FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0642 0645 062D;;;;N;;;;;
+FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0642 0645 0645;;;;N;;;;;
+FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062D 0645;;;;N;;;;;
+FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062D 064A;;;;N;;;;;
+FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 062D 0649;;;;N;;;;;
+FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 062C;;;;N;;;;;
+FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 062C;;;;N;;;;;
+FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062E 0645;;;;N;;;;;
+FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062E 0645;;;;N;;;;;
+FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0644 0645 062D;;;;N;;;;;
+FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 0645 062D;;;;N;;;;;
+FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 062C;;;;N;;;;;
+FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 0645;;;;N;;;;;
+FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062D 064A;;;;N;;;;;
+FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062D;;;;N;;;;;
+FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C 0645;;;;N;;;;;
+FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 062C;;;;N;;;;;
+FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 0645;;;;N;;;;;
+FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062E;;;;N;;;;;
+FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 062C;;;;N;;;;;
+FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 0645;;;;N;;;;;
+FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062D 0645;;;;N;;;;;
+FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062D 0649;;;;N;;;;;
+FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 062C 0645;;;;N;;;;;
+FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C 0645;;;;N;;;;;
+FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062C 0649;;;;N;;;;;
+FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 0645 064A;;;;N;;;;;
+FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0645 0649;;;;N;;;;;
+FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645 0645;;;;N;;;;;
+FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645 0645;;;;N;;;;;
+FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062E 064A;;;;N;;;;;
+FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062C 064A;;;;N;;;;;
+FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062C 0649;;;;N;;;;;
+FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062E 064A;;;;N;;;;;
+FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062E 0649;;;;N;;;;;
+FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 0645 064A;;;;N;;;;;
+FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0645 0649;;;;N;;;;;
+FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 0645 064A;;;;N;;;;;
+FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 062D 0649;;;;N;;;;;
+FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0645 0649;;;;N;;;;;
+FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062E 0649;;;;N;;;;;
+FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 062D 064A;;;;N;;;;;
+FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062D 064A;;;;N;;;;;
+FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 062D 064A;;;;N;;;;;
+FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062C 064A;;;;N;;;;;
+FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 0645 064A;;;;N;;;;;
+FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062D 064A;;;;N;;;;;
+FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062C 064A;;;;N;;;;;
+FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 0645 064A;;;;N;;;;;
+FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 0645 064A;;;;N;;;;;
+FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 0645 064A;;;;N;;;;;
+FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062D 064A;;;;N;;;;;
+FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 0645 062D;;;;N;;;;;
+FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062D 0645;;;;N;;;;;
+FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 0645 064A;;;;N;;;;;
+FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 0645 064A;;;;N;;;;;
+FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062C 062D;;;;N;;;;;
+FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062E 064A;;;;N;;;;;
+FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 0645;;;;N;;;;;
+FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645 0645;;;;N;;;;;
+FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 0645;;;;N;;;;;
+FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0646 062C 062D;;;;N;;;;;
+FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 062D 064A;;;;N;;;;;
+FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 062C 064A;;;;N;;;;;
+FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062C 064A;;;;N;;;;;
+FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 0645 064A;;;;N;;;;;
+FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062D 064A;;;;N;;;;;
+FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645 0645;;;;N;;;;;
+FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C 0645;;;;N;;;;;
+FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645 0645;;;;N;;;;;
+FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 062E 064A;;;;N;;;;;
+FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062C 064A;;;;N;;;;;
+FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 06D2;;;;N;;;;;
+FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0642 0644 06D2;;;;N;;;;;
+FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL;<isolated> 0627 0644 0644 0647;;;;N;;;;;
+FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL;<isolated> 0627 0643 0628 0631;;;;N;;;;;
+FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D 0645 062F;;;;N;;;;;
+FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0639 0645;;;;N;;;;;
+FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL;<isolated> 0631 0633 0648 0644;;;;N;;;;;
+FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL;<isolated> 0639 0644 064A 0647;;;;N;;;;;
+FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL;<isolated> 0648 0633 0644 0645;;;;N;;;;;
+FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0649;;;;N;;;;;
+FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL;<isolated> 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;;
+FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL;<isolated> 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;;
+FDFC;RIAL SIGN;Sc;0;AL;<isolated> 0631 06CC 0627 0644;;;;N;;;;;
+FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;;
+FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;;
+FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;;
+FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;;
+FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;;
+FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;;
+FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;;
+FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;;
+FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;;
+FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;;
+FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;;
+FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;;
+FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;;
+FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;;
+FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;;
+FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;;
+FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;;
+FE10;PRESENTATION FORM FOR VERTICAL COMMA;Po;0;ON;<vertical> 002C;;;;N;;;;;
+FE11;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA;Po;0;ON;<vertical> 3001;;;;N;;;;;
+FE12;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP;Po;0;ON;<vertical> 3002;;;;N;;;;;
+FE13;PRESENTATION FORM FOR VERTICAL COLON;Po;0;ON;<vertical> 003A;;;;N;;;;;
+FE14;PRESENTATION FORM FOR VERTICAL SEMICOLON;Po;0;ON;<vertical> 003B;;;;N;;;;;
+FE15;PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK;Po;0;ON;<vertical> 0021;;;;N;;;;;
+FE16;PRESENTATION FORM FOR VERTICAL QUESTION MARK;Po;0;ON;<vertical> 003F;;;;N;;;;;
+FE17;PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;<vertical> 3016;;;;N;;;;;
+FE18;PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET;Pe;0;ON;<vertical> 3017;;;;N;;;;;
+FE19;PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS;Po;0;ON;<vertical> 2026;;;;N;;;;;
+FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;;
+FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;;
+FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;;
+FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;;
+FE24;COMBINING MACRON LEFT HALF;Mn;230;NSM;;;;;N;;;;;
+FE25;COMBINING MACRON RIGHT HALF;Mn;230;NSM;;;;;N;;;;;
+FE26;COMBINING CONJOINING MACRON;Mn;230;NSM;;;;;N;;;;;
+FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON;<vertical> 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;;
+FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON;<vertical> 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;;
+FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON;<vertical> 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;;
+FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;;
+FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;;
+FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON;<vertical> 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;;
+FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON;<vertical> 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;;
+FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON;<vertical> 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;;
+FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON;<vertical> 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;;
+FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<vertical> 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;;
+FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<vertical> 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;;
+FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;<vertical> 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;;
+FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;<vertical> 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;;
+FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;<vertical> 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;;
+FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;<vertical> 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;;
+FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON;<vertical> 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;;
+FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON;<vertical> 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;;
+FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON;<vertical> 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;;
+FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON;<vertical> 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;;
+FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON;<vertical> 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;;
+FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON;<vertical> 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;;
+FE45;SESAME DOT;Po;0;ON;;;;;N;;;;;
+FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;;
+FE47;PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET;Ps;0;ON;<vertical> 005B;;;;N;;;;;
+FE48;PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET;Pe;0;ON;<vertical> 005D;;;;N;;;;;
+FE49;DASHED OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DASHED OVERSCORE;;;;
+FE4A;CENTRELINE OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;;
+FE4B;WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING WAVY OVERSCORE;;;;
+FE4C;DOUBLE WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;;
+FE4D;DASHED LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING DASHED UNDERSCORE;;;;
+FE4E;CENTRELINE LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;;
+FE4F;WAVY LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING WAVY UNDERSCORE;;;;
+FE50;SMALL COMMA;Po;0;CS;<small> 002C;;;;N;;;;;
+FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON;<small> 3001;;;;N;;;;;
+FE52;SMALL FULL STOP;Po;0;CS;<small> 002E;;;;N;SMALL PERIOD;;;;
+FE54;SMALL SEMICOLON;Po;0;ON;<small> 003B;;;;N;;;;;
+FE55;SMALL COLON;Po;0;CS;<small> 003A;;;;N;;;;;
+FE56;SMALL QUESTION MARK;Po;0;ON;<small> 003F;;;;N;;;;;
+FE57;SMALL EXCLAMATION MARK;Po;0;ON;<small> 0021;;;;N;;;;;
+FE58;SMALL EM DASH;Pd;0;ON;<small> 2014;;;;N;;;;;
+FE59;SMALL LEFT PARENTHESIS;Ps;0;ON;<small> 0028;;;;Y;SMALL OPENING PARENTHESIS;;;;
+FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON;<small> 0029;;;;Y;SMALL CLOSING PARENTHESIS;;;;
+FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON;<small> 007B;;;;Y;SMALL OPENING CURLY BRACKET;;;;
+FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON;<small> 007D;;;;Y;SMALL CLOSING CURLY BRACKET;;;;
+FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<small> 3014;;;;Y;SMALL OPENING TORTOISE SHELL BRACKET;;;;
+FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<small> 3015;;;;Y;SMALL CLOSING TORTOISE SHELL BRACKET;;;;
+FE5F;SMALL NUMBER SIGN;Po;0;ET;<small> 0023;;;;N;;;;;
+FE60;SMALL AMPERSAND;Po;0;ON;<small> 0026;;;;N;;;;;
+FE61;SMALL ASTERISK;Po;0;ON;<small> 002A;;;;N;;;;;
+FE62;SMALL PLUS SIGN;Sm;0;ES;<small> 002B;;;;N;;;;;
+FE63;SMALL HYPHEN-MINUS;Pd;0;ES;<small> 002D;;;;N;;;;;
+FE64;SMALL LESS-THAN SIGN;Sm;0;ON;<small> 003C;;;;Y;;;;;
+FE65;SMALL GREATER-THAN SIGN;Sm;0;ON;<small> 003E;;;;Y;;;;;
+FE66;SMALL EQUALS SIGN;Sm;0;ON;<small> 003D;;;;N;;;;;
+FE68;SMALL REVERSE SOLIDUS;Po;0;ON;<small> 005C;;;;N;SMALL BACKSLASH;;;;
+FE69;SMALL DOLLAR SIGN;Sc;0;ET;<small> 0024;;;;N;;;;;
+FE6A;SMALL PERCENT SIGN;Po;0;ET;<small> 0025;;;;N;;;;;
+FE6B;SMALL COMMERCIAL AT;Po;0;ON;<small> 0040;;;;N;;;;;
+FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;;
+FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL;<medial> 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;;
+FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;;
+FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;;
+FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;;
+FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E;;;;N;ARABIC SPACING FATHAH;;;;
+FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;;
+FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;;
+FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;;
+FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650;;;;N;ARABIC SPACING KASRAH;;;;
+FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;;
+FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;;
+FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL;<medial> 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;;
+FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL;<isolated> 0020 0652;;;;N;ARABIC SPACING SUKUN;;;;
+FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL;<medial> 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;;
+FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL;<isolated> 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;;
+FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;;
+FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;;
+FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;;
+FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;;
+FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;;
+FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;;
+FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;;
+FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;;
+FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;;
+FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;;
+FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL;<initial> 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;;
+FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL;<medial> 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;;
+FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;;
+FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL;<final> 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;;
+FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL;<isolated> 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;;
+FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL;<final> 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;;
+FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL;<initial> 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;;
+FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL;<medial> 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;;
+FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL;<isolated> 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;;
+FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL;<final> 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;;
+FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL;<isolated> 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;;
+FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL;<final> 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;;
+FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL;<initial> 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;;
+FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL;<medial> 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;;
+FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL;<isolated> 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;;
+FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL;<final> 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;;
+FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL;<initial> 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;;
+FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL;<medial> 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;;
+FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;;
+FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL;<final> 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;;
+FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL;<initial> 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;;
+FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL;<medial> 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;;
+FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL;<isolated> 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;;
+FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL;<final> 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;;
+FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL;<initial> 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;;
+FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL;<medial> 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;;
+FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;;
+FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL;<final> 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;;
+FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL;<initial> 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;;
+FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL;<medial> 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;;
+FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL;<isolated> 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;;
+FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL;<final> 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;;
+FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL;<isolated> 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;;
+FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL;<final> 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;;
+FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL;<isolated> 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;;
+FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL;<final> 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;;
+FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL;<isolated> 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;;
+FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL;<final> 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;;
+FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL;<isolated> 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;;
+FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL;<final> 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;;
+FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL;<initial> 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;;
+FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL;<medial> 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;;
+FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL;<isolated> 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;;
+FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL;<final> 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;;
+FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL;<initial> 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;;
+FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL;<medial> 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;;
+FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL;<isolated> 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;;
+FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL;<final> 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;;
+FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL;<initial> 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;;
+FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL;<medial> 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;;
+FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL;<isolated> 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;;
+FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL;<final> 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;;
+FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL;<initial> 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;;
+FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL;<medial> 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;;
+FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL;<isolated> 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;;
+FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL;<final> 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;;
+FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL;<initial> 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;;
+FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL;<medial> 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;;
+FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL;<isolated> 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;;
+FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL;<final> 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;;
+FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL;<initial> 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;;
+FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL;<medial> 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;;
+FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL;<isolated> 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;;
+FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL;<final> 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;;
+FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL;<initial> 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;;
+FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL;<medial> 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;;
+FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL;<isolated> 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;;
+FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL;<final> 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;;
+FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL;<initial> 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;;
+FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL;<medial> 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;;
+FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL;<isolated> 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;;
+FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL;<final> 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;;
+FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL;<initial> 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;;
+FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL;<medial> 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;;
+FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL;<isolated> 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;;
+FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL;<final> 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;;
+FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL;<initial> 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;;
+FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL;<medial> 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;;
+FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL;<isolated> 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;;
+FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL;<final> 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;;
+FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL;<initial> 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;;
+FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL;<medial> 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;;
+FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL;<isolated> 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;;
+FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL;<final> 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;;
+FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL;<initial> 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;;
+FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL;<medial> 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;;
+FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;;
+FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL;<final> 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;;
+FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL;<initial> 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;;
+FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL;<medial> 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;;
+FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL;<isolated> 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;;
+FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL;<final> 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;;
+FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL;<initial> 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;;
+FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL;<medial> 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;;
+FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL;<isolated> 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;;
+FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL;<final> 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;;
+FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL;<initial> 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;;
+FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL;<medial> 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;;
+FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL;<isolated> 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;;
+FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL;<final> 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;;
+FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;;
+FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;;
+FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;;
+FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL;<final> 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;;
+FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL;<initial> 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;;
+FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL;<medial> 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;;
+FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;;
+FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;;
+FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;;
+FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;;
+FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;;
+FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;;
+FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;;
+FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;;
+FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
+FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON;<wide> 0021;;;;N;;;;;
+FF02;FULLWIDTH QUOTATION MARK;Po;0;ON;<wide> 0022;;;;N;;;;;
+FF03;FULLWIDTH NUMBER SIGN;Po;0;ET;<wide> 0023;;;;N;;;;;
+FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET;<wide> 0024;;;;N;;;;;
+FF05;FULLWIDTH PERCENT SIGN;Po;0;ET;<wide> 0025;;;;N;;;;;
+FF06;FULLWIDTH AMPERSAND;Po;0;ON;<wide> 0026;;;;N;;;;;
+FF07;FULLWIDTH APOSTROPHE;Po;0;ON;<wide> 0027;;;;N;;;;;
+FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON;<wide> 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;;
+FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON;<wide> 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;;
+FF0A;FULLWIDTH ASTERISK;Po;0;ON;<wide> 002A;;;;N;;;;;
+FF0B;FULLWIDTH PLUS SIGN;Sm;0;ES;<wide> 002B;;;;N;;;;;
+FF0C;FULLWIDTH COMMA;Po;0;CS;<wide> 002C;;;;N;;;;;
+FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ES;<wide> 002D;;;;N;;;;;
+FF0E;FULLWIDTH FULL STOP;Po;0;CS;<wide> 002E;;;;N;FULLWIDTH PERIOD;;;;
+FF0F;FULLWIDTH SOLIDUS;Po;0;CS;<wide> 002F;;;;N;FULLWIDTH SLASH;;;;
+FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN;<wide> 0030;0;0;0;N;;;;;
+FF11;FULLWIDTH DIGIT ONE;Nd;0;EN;<wide> 0031;1;1;1;N;;;;;
+FF12;FULLWIDTH DIGIT TWO;Nd;0;EN;<wide> 0032;2;2;2;N;;;;;
+FF13;FULLWIDTH DIGIT THREE;Nd;0;EN;<wide> 0033;3;3;3;N;;;;;
+FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN;<wide> 0034;4;4;4;N;;;;;
+FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN;<wide> 0035;5;5;5;N;;;;;
+FF16;FULLWIDTH DIGIT SIX;Nd;0;EN;<wide> 0036;6;6;6;N;;;;;
+FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN;<wide> 0037;7;7;7;N;;;;;
+FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN;<wide> 0038;8;8;8;N;;;;;
+FF19;FULLWIDTH DIGIT NINE;Nd;0;EN;<wide> 0039;9;9;9;N;;;;;
+FF1A;FULLWIDTH COLON;Po;0;CS;<wide> 003A;;;;N;;;;;
+FF1B;FULLWIDTH SEMICOLON;Po;0;ON;<wide> 003B;;;;N;;;;;
+FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON;<wide> 003C;;;;Y;;;;;
+FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON;<wide> 003D;;;;N;;;;;
+FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON;<wide> 003E;;;;Y;;;;;
+FF1F;FULLWIDTH QUESTION MARK;Po;0;ON;<wide> 003F;;;;N;;;;;
+FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON;<wide> 0040;;;;N;;;;;
+FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L;<wide> 0041;;;;N;;;;FF41;
+FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L;<wide> 0042;;;;N;;;;FF42;
+FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L;<wide> 0043;;;;N;;;;FF43;
+FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L;<wide> 0044;;;;N;;;;FF44;
+FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L;<wide> 0045;;;;N;;;;FF45;
+FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L;<wide> 0046;;;;N;;;;FF46;
+FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L;<wide> 0047;;;;N;;;;FF47;
+FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L;<wide> 0048;;;;N;;;;FF48;
+FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L;<wide> 0049;;;;N;;;;FF49;
+FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L;<wide> 004A;;;;N;;;;FF4A;
+FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L;<wide> 004B;;;;N;;;;FF4B;
+FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L;<wide> 004C;;;;N;;;;FF4C;
+FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L;<wide> 004D;;;;N;;;;FF4D;
+FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L;<wide> 004E;;;;N;;;;FF4E;
+FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L;<wide> 004F;;;;N;;;;FF4F;
+FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L;<wide> 0050;;;;N;;;;FF50;
+FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L;<wide> 0051;;;;N;;;;FF51;
+FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L;<wide> 0052;;;;N;;;;FF52;
+FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L;<wide> 0053;;;;N;;;;FF53;
+FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L;<wide> 0054;;;;N;;;;FF54;
+FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L;<wide> 0055;;;;N;;;;FF55;
+FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L;<wide> 0056;;;;N;;;;FF56;
+FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L;<wide> 0057;;;;N;;;;FF57;
+FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L;<wide> 0058;;;;N;;;;FF58;
+FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L;<wide> 0059;;;;N;;;;FF59;
+FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L;<wide> 005A;;;;N;;;;FF5A;
+FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON;<wide> 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;;
+FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON;<wide> 005C;;;;N;FULLWIDTH BACKSLASH;;;;
+FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON;<wide> 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;;
+FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON;<wide> 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;;
+FF3F;FULLWIDTH LOW LINE;Pc;0;ON;<wide> 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;;
+FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON;<wide> 0060;;;;N;FULLWIDTH SPACING GRAVE;;;;
+FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L;<wide> 0061;;;;N;;;FF21;;FF21
+FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L;<wide> 0062;;;;N;;;FF22;;FF22
+FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L;<wide> 0063;;;;N;;;FF23;;FF23
+FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L;<wide> 0064;;;;N;;;FF24;;FF24
+FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L;<wide> 0065;;;;N;;;FF25;;FF25
+FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L;<wide> 0066;;;;N;;;FF26;;FF26
+FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L;<wide> 0067;;;;N;;;FF27;;FF27
+FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L;<wide> 0068;;;;N;;;FF28;;FF28
+FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L;<wide> 0069;;;;N;;;FF29;;FF29
+FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L;<wide> 006A;;;;N;;;FF2A;;FF2A
+FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L;<wide> 006B;;;;N;;;FF2B;;FF2B
+FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L;<wide> 006C;;;;N;;;FF2C;;FF2C
+FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L;<wide> 006D;;;;N;;;FF2D;;FF2D
+FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L;<wide> 006E;;;;N;;;FF2E;;FF2E
+FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L;<wide> 006F;;;;N;;;FF2F;;FF2F
+FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L;<wide> 0070;;;;N;;;FF30;;FF30
+FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L;<wide> 0071;;;;N;;;FF31;;FF31
+FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L;<wide> 0072;;;;N;;;FF32;;FF32
+FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L;<wide> 0073;;;;N;;;FF33;;FF33
+FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L;<wide> 0074;;;;N;;;FF34;;FF34
+FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L;<wide> 0075;;;;N;;;FF35;;FF35
+FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L;<wide> 0076;;;;N;;;FF36;;FF36
+FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L;<wide> 0077;;;;N;;;FF37;;FF37
+FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L;<wide> 0078;;;;N;;;FF38;;FF38
+FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L;<wide> 0079;;;;N;;;FF39;;FF39
+FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L;<wide> 007A;;;;N;;;FF3A;;FF3A
+FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON;<wide> 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;;
+FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON;<wide> 007C;;;;N;FULLWIDTH VERTICAL BAR;;;;
+FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON;<wide> 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;;
+FF5E;FULLWIDTH TILDE;Sm;0;ON;<wide> 007E;;;;N;FULLWIDTH SPACING TILDE;;;;
+FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON;<wide> 2985;;;;Y;;;;;
+FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON;<wide> 2986;;;;Y;;;;;
+FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON;<narrow> 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;;
+FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON;<narrow> 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;;
+FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON;<narrow> 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;;
+FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON;<narrow> 3001;;;;N;;;;;
+FF65;HALFWIDTH KATAKANA MIDDLE DOT;Po;0;ON;<narrow> 30FB;;;;N;;;;;
+FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L;<narrow> 30F2;;;;N;;;;;
+FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L;<narrow> 30A1;;;;N;;;;;
+FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L;<narrow> 30A3;;;;N;;;;;
+FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L;<narrow> 30A5;;;;N;;;;;
+FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L;<narrow> 30A7;;;;N;;;;;
+FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L;<narrow> 30A9;;;;N;;;;;
+FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L;<narrow> 30E3;;;;N;;;;;
+FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L;<narrow> 30E5;;;;N;;;;;
+FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L;<narrow> 30E7;;;;N;;;;;
+FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L;<narrow> 30C3;;;;N;;;;;
+FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;<narrow> 30FC;;;;N;;;;;
+FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L;<narrow> 30A2;;;;N;;;;;
+FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L;<narrow> 30A4;;;;N;;;;;
+FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L;<narrow> 30A6;;;;N;;;;;
+FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L;<narrow> 30A8;;;;N;;;;;
+FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L;<narrow> 30AA;;;;N;;;;;
+FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L;<narrow> 30AB;;;;N;;;;;
+FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L;<narrow> 30AD;;;;N;;;;;
+FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L;<narrow> 30AF;;;;N;;;;;
+FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L;<narrow> 30B1;;;;N;;;;;
+FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L;<narrow> 30B3;;;;N;;;;;
+FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L;<narrow> 30B5;;;;N;;;;;
+FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L;<narrow> 30B7;;;;N;;;;;
+FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L;<narrow> 30B9;;;;N;;;;;
+FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L;<narrow> 30BB;;;;N;;;;;
+FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L;<narrow> 30BD;;;;N;;;;;
+FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L;<narrow> 30BF;;;;N;;;;;
+FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L;<narrow> 30C1;;;;N;;;;;
+FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L;<narrow> 30C4;;;;N;;;;;
+FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L;<narrow> 30C6;;;;N;;;;;
+FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L;<narrow> 30C8;;;;N;;;;;
+FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L;<narrow> 30CA;;;;N;;;;;
+FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L;<narrow> 30CB;;;;N;;;;;
+FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L;<narrow> 30CC;;;;N;;;;;
+FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L;<narrow> 30CD;;;;N;;;;;
+FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L;<narrow> 30CE;;;;N;;;;;
+FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L;<narrow> 30CF;;;;N;;;;;
+FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L;<narrow> 30D2;;;;N;;;;;
+FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L;<narrow> 30D5;;;;N;;;;;
+FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L;<narrow> 30D8;;;;N;;;;;
+FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L;<narrow> 30DB;;;;N;;;;;
+FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L;<narrow> 30DE;;;;N;;;;;
+FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L;<narrow> 30DF;;;;N;;;;;
+FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L;<narrow> 30E0;;;;N;;;;;
+FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L;<narrow> 30E1;;;;N;;;;;
+FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L;<narrow> 30E2;;;;N;;;;;
+FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L;<narrow> 30E4;;;;N;;;;;
+FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L;<narrow> 30E6;;;;N;;;;;
+FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L;<narrow> 30E8;;;;N;;;;;
+FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L;<narrow> 30E9;;;;N;;;;;
+FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L;<narrow> 30EA;;;;N;;;;;
+FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L;<narrow> 30EB;;;;N;;;;;
+FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L;<narrow> 30EC;;;;N;;;;;
+FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L;<narrow> 30ED;;;;N;;;;;
+FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L;<narrow> 30EF;;;;N;;;;;
+FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L;<narrow> 30F3;;;;N;;;;;
+FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L;<narrow> 3099;;;;N;;;;;
+FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L;<narrow> 309A;;;;N;;;;;
+FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L;<narrow> 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;;
+FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L;<narrow> 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;;
+FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L;<narrow> 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;;
+FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<narrow> 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;;
+FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L;<narrow> 3134;;;;N;;;;;
+FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<narrow> 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;;
+FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<narrow> 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;;
+FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L;<narrow> 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;;
+FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L;<narrow> 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;;
+FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L;<narrow> 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;;
+FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<narrow> 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;;
+FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<narrow> 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;;
+FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<narrow> 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;;
+FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L;<narrow> 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;;
+FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<narrow> 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;;
+FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<narrow> 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;;
+FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<narrow> 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;;
+FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L;<narrow> 3141;;;;N;;;;;
+FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L;<narrow> 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;;
+FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L;<narrow> 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;;
+FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L;<narrow> 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;;
+FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L;<narrow> 3145;;;;N;;;;;
+FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L;<narrow> 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;;
+FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L;<narrow> 3147;;;;N;;;;;
+FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L;<narrow> 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;;
+FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L;<narrow> 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;;
+FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L;<narrow> 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;;
+FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L;<narrow> 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;;
+FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L;<narrow> 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;;
+FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L;<narrow> 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;;
+FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L;<narrow> 314E;;;;N;;;;;
+FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L;<narrow> 314F;;;;N;;;;;
+FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L;<narrow> 3150;;;;N;;;;;
+FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L;<narrow> 3151;;;;N;;;;;
+FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L;<narrow> 3152;;;;N;;;;;
+FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L;<narrow> 3153;;;;N;;;;;
+FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L;<narrow> 3154;;;;N;;;;;
+FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L;<narrow> 3155;;;;N;;;;;
+FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L;<narrow> 3156;;;;N;;;;;
+FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L;<narrow> 3157;;;;N;;;;;
+FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L;<narrow> 3158;;;;N;;;;;
+FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L;<narrow> 3159;;;;N;;;;;
+FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L;<narrow> 315A;;;;N;;;;;
+FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L;<narrow> 315B;;;;N;;;;;
+FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L;<narrow> 315C;;;;N;;;;;
+FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L;<narrow> 315D;;;;N;;;;;
+FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L;<narrow> 315E;;;;N;;;;;
+FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L;<narrow> 315F;;;;N;;;;;
+FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L;<narrow> 3160;;;;N;;;;;
+FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L;<narrow> 3161;;;;N;;;;;
+FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L;<narrow> 3162;;;;N;;;;;
+FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L;<narrow> 3163;;;;N;;;;;
+FFE0;FULLWIDTH CENT SIGN;Sc;0;ET;<wide> 00A2;;;;N;;;;;
+FFE1;FULLWIDTH POUND SIGN;Sc;0;ET;<wide> 00A3;;;;N;;;;;
+FFE2;FULLWIDTH NOT SIGN;Sm;0;ON;<wide> 00AC;;;;N;;;;;
+FFE3;FULLWIDTH MACRON;Sk;0;ON;<wide> 00AF;;;;N;FULLWIDTH SPACING MACRON;;;;
+FFE4;FULLWIDTH BROKEN BAR;So;0;ON;<wide> 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;;
+FFE5;FULLWIDTH YEN SIGN;Sc;0;ET;<wide> 00A5;;;;N;;;;;
+FFE6;FULLWIDTH WON SIGN;Sc;0;ET;<wide> 20A9;;;;N;;;;;
+FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON;<narrow> 2502;;;;N;;;;;
+FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON;<narrow> 2190;;;;N;;;;;
+FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON;<narrow> 2191;;;;N;;;;;
+FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON;<narrow> 2192;;;;N;;;;;
+FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON;<narrow> 2193;;;;N;;;;;
+FFED;HALFWIDTH BLACK SQUARE;So;0;ON;<narrow> 25A0;;;;N;;;;;
+FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON;<narrow> 25CB;;;;N;;;;;
+FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;ON;;;;;N;;;;;
+FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;ON;;;;;N;;;;;
+FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;ON;;;;;N;;;;;
+FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
+FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
+10000;LINEAR B SYLLABLE B008 A;Lo;0;L;;;;;N;;;;;
+10001;LINEAR B SYLLABLE B038 E;Lo;0;L;;;;;N;;;;;
+10002;LINEAR B SYLLABLE B028 I;Lo;0;L;;;;;N;;;;;
+10003;LINEAR B SYLLABLE B061 O;Lo;0;L;;;;;N;;;;;
+10004;LINEAR B SYLLABLE B010 U;Lo;0;L;;;;;N;;;;;
+10005;LINEAR B SYLLABLE B001 DA;Lo;0;L;;;;;N;;;;;
+10006;LINEAR B SYLLABLE B045 DE;Lo;0;L;;;;;N;;;;;
+10007;LINEAR B SYLLABLE B007 DI;Lo;0;L;;;;;N;;;;;
+10008;LINEAR B SYLLABLE B014 DO;Lo;0;L;;;;;N;;;;;
+10009;LINEAR B SYLLABLE B051 DU;Lo;0;L;;;;;N;;;;;
+1000A;LINEAR B SYLLABLE B057 JA;Lo;0;L;;;;;N;;;;;
+1000B;LINEAR B SYLLABLE B046 JE;Lo;0;L;;;;;N;;;;;
+1000D;LINEAR B SYLLABLE B036 JO;Lo;0;L;;;;;N;;;;;
+1000E;LINEAR B SYLLABLE B065 JU;Lo;0;L;;;;;N;;;;;
+1000F;LINEAR B SYLLABLE B077 KA;Lo;0;L;;;;;N;;;;;
+10010;LINEAR B SYLLABLE B044 KE;Lo;0;L;;;;;N;;;;;
+10011;LINEAR B SYLLABLE B067 KI;Lo;0;L;;;;;N;;;;;
+10012;LINEAR B SYLLABLE B070 KO;Lo;0;L;;;;;N;;;;;
+10013;LINEAR B SYLLABLE B081 KU;Lo;0;L;;;;;N;;;;;
+10014;LINEAR B SYLLABLE B080 MA;Lo;0;L;;;;;N;;;;;
+10015;LINEAR B SYLLABLE B013 ME;Lo;0;L;;;;;N;;;;;
+10016;LINEAR B SYLLABLE B073 MI;Lo;0;L;;;;;N;;;;;
+10017;LINEAR B SYLLABLE B015 MO;Lo;0;L;;;;;N;;;;;
+10018;LINEAR B SYLLABLE B023 MU;Lo;0;L;;;;;N;;;;;
+10019;LINEAR B SYLLABLE B006 NA;Lo;0;L;;;;;N;;;;;
+1001A;LINEAR B SYLLABLE B024 NE;Lo;0;L;;;;;N;;;;;
+1001B;LINEAR B SYLLABLE B030 NI;Lo;0;L;;;;;N;;;;;
+1001C;LINEAR B SYLLABLE B052 NO;Lo;0;L;;;;;N;;;;;
+1001D;LINEAR B SYLLABLE B055 NU;Lo;0;L;;;;;N;;;;;
+1001E;LINEAR B SYLLABLE B003 PA;Lo;0;L;;;;;N;;;;;
+1001F;LINEAR B SYLLABLE B072 PE;Lo;0;L;;;;;N;;;;;
+10020;LINEAR B SYLLABLE B039 PI;Lo;0;L;;;;;N;;;;;
+10021;LINEAR B SYLLABLE B011 PO;Lo;0;L;;;;;N;;;;;
+10022;LINEAR B SYLLABLE B050 PU;Lo;0;L;;;;;N;;;;;
+10023;LINEAR B SYLLABLE B016 QA;Lo;0;L;;;;;N;;;;;
+10024;LINEAR B SYLLABLE B078 QE;Lo;0;L;;;;;N;;;;;
+10025;LINEAR B SYLLABLE B021 QI;Lo;0;L;;;;;N;;;;;
+10026;LINEAR B SYLLABLE B032 QO;Lo;0;L;;;;;N;;;;;
+10028;LINEAR B SYLLABLE B060 RA;Lo;0;L;;;;;N;;;;;
+10029;LINEAR B SYLLABLE B027 RE;Lo;0;L;;;;;N;;;;;
+1002A;LINEAR B SYLLABLE B053 RI;Lo;0;L;;;;;N;;;;;
+1002B;LINEAR B SYLLABLE B002 RO;Lo;0;L;;;;;N;;;;;
+1002C;LINEAR B SYLLABLE B026 RU;Lo;0;L;;;;;N;;;;;
+1002D;LINEAR B SYLLABLE B031 SA;Lo;0;L;;;;;N;;;;;
+1002E;LINEAR B SYLLABLE B009 SE;Lo;0;L;;;;;N;;;;;
+1002F;LINEAR B SYLLABLE B041 SI;Lo;0;L;;;;;N;;;;;
+10030;LINEAR B SYLLABLE B012 SO;Lo;0;L;;;;;N;;;;;
+10031;LINEAR B SYLLABLE B058 SU;Lo;0;L;;;;;N;;;;;
+10032;LINEAR B SYLLABLE B059 TA;Lo;0;L;;;;;N;;;;;
+10033;LINEAR B SYLLABLE B004 TE;Lo;0;L;;;;;N;;;;;
+10034;LINEAR B SYLLABLE B037 TI;Lo;0;L;;;;;N;;;;;
+10035;LINEAR B SYLLABLE B005 TO;Lo;0;L;;;;;N;;;;;
+10036;LINEAR B SYLLABLE B069 TU;Lo;0;L;;;;;N;;;;;
+10037;LINEAR B SYLLABLE B054 WA;Lo;0;L;;;;;N;;;;;
+10038;LINEAR B SYLLABLE B075 WE;Lo;0;L;;;;;N;;;;;
+10039;LINEAR B SYLLABLE B040 WI;Lo;0;L;;;;;N;;;;;
+1003A;LINEAR B SYLLABLE B042 WO;Lo;0;L;;;;;N;;;;;
+1003C;LINEAR B SYLLABLE B017 ZA;Lo;0;L;;;;;N;;;;;
+1003D;LINEAR B SYLLABLE B074 ZE;Lo;0;L;;;;;N;;;;;
+1003F;LINEAR B SYLLABLE B020 ZO;Lo;0;L;;;;;N;;;;;
+10040;LINEAR B SYLLABLE B025 A2;Lo;0;L;;;;;N;;;;;
+10041;LINEAR B SYLLABLE B043 A3;Lo;0;L;;;;;N;;;;;
+10042;LINEAR B SYLLABLE B085 AU;Lo;0;L;;;;;N;;;;;
+10043;LINEAR B SYLLABLE B071 DWE;Lo;0;L;;;;;N;;;;;
+10044;LINEAR B SYLLABLE B090 DWO;Lo;0;L;;;;;N;;;;;
+10045;LINEAR B SYLLABLE B048 NWA;Lo;0;L;;;;;N;;;;;
+10046;LINEAR B SYLLABLE B029 PU2;Lo;0;L;;;;;N;;;;;
+10047;LINEAR B SYLLABLE B062 PTE;Lo;0;L;;;;;N;;;;;
+10048;LINEAR B SYLLABLE B076 RA2;Lo;0;L;;;;;N;;;;;
+10049;LINEAR B SYLLABLE B033 RA3;Lo;0;L;;;;;N;;;;;
+1004A;LINEAR B SYLLABLE B068 RO2;Lo;0;L;;;;;N;;;;;
+1004B;LINEAR B SYLLABLE B066 TA2;Lo;0;L;;;;;N;;;;;
+1004C;LINEAR B SYLLABLE B087 TWE;Lo;0;L;;;;;N;;;;;
+1004D;LINEAR B SYLLABLE B091 TWO;Lo;0;L;;;;;N;;;;;
+10050;LINEAR B SYMBOL B018;Lo;0;L;;;;;N;;;;;
+10051;LINEAR B SYMBOL B019;Lo;0;L;;;;;N;;;;;
+10052;LINEAR B SYMBOL B022;Lo;0;L;;;;;N;;;;;
+10053;LINEAR B SYMBOL B034;Lo;0;L;;;;;N;;;;;
+10054;LINEAR B SYMBOL B047;Lo;0;L;;;;;N;;;;;
+10055;LINEAR B SYMBOL B049;Lo;0;L;;;;;N;;;;;
+10056;LINEAR B SYMBOL B056;Lo;0;L;;;;;N;;;;;
+10057;LINEAR B SYMBOL B063;Lo;0;L;;;;;N;;;;;
+10058;LINEAR B SYMBOL B064;Lo;0;L;;;;;N;;;;;
+10059;LINEAR B SYMBOL B079;Lo;0;L;;;;;N;;;;;
+1005A;LINEAR B SYMBOL B082;Lo;0;L;;;;;N;;;;;
+1005B;LINEAR B SYMBOL B083;Lo;0;L;;;;;N;;;;;
+1005C;LINEAR B SYMBOL B086;Lo;0;L;;;;;N;;;;;
+1005D;LINEAR B SYMBOL B089;Lo;0;L;;;;;N;;;;;
+10080;LINEAR B IDEOGRAM B100 MAN;Lo;0;L;;;;;N;;;;;
+10081;LINEAR B IDEOGRAM B102 WOMAN;Lo;0;L;;;;;N;;;;;
+10082;LINEAR B IDEOGRAM B104 DEER;Lo;0;L;;;;;N;;;;;
+10083;LINEAR B IDEOGRAM B105 EQUID;Lo;0;L;;;;;N;;;;;
+10084;LINEAR B IDEOGRAM B105F MARE;Lo;0;L;;;;;N;;;;;
+10085;LINEAR B IDEOGRAM B105M STALLION;Lo;0;L;;;;;N;;;;;
+10086;LINEAR B IDEOGRAM B106F EWE;Lo;0;L;;;;;N;;;;;
+10087;LINEAR B IDEOGRAM B106M RAM;Lo;0;L;;;;;N;;;;;
+10088;LINEAR B IDEOGRAM B107F SHE-GOAT;Lo;0;L;;;;;N;;;;;
+10089;LINEAR B IDEOGRAM B107M HE-GOAT;Lo;0;L;;;;;N;;;;;
+1008A;LINEAR B IDEOGRAM B108F SOW;Lo;0;L;;;;;N;;;;;
+1008B;LINEAR B IDEOGRAM B108M BOAR;Lo;0;L;;;;;N;;;;;
+1008C;LINEAR B IDEOGRAM B109F COW;Lo;0;L;;;;;N;;;;;
+1008D;LINEAR B IDEOGRAM B109M BULL;Lo;0;L;;;;;N;;;;;
+1008E;LINEAR B IDEOGRAM B120 WHEAT;Lo;0;L;;;;;N;;;;;
+1008F;LINEAR B IDEOGRAM B121 BARLEY;Lo;0;L;;;;;N;;;;;
+10090;LINEAR B IDEOGRAM B122 OLIVE;Lo;0;L;;;;;N;;;;;
+10091;LINEAR B IDEOGRAM B123 SPICE;Lo;0;L;;;;;N;;;;;
+10092;LINEAR B IDEOGRAM B125 CYPERUS;Lo;0;L;;;;;N;;;;;
+10093;LINEAR B MONOGRAM B127 KAPO;Lo;0;L;;;;;N;;;;;
+10094;LINEAR B MONOGRAM B128 KANAKO;Lo;0;L;;;;;N;;;;;
+10095;LINEAR B IDEOGRAM B130 OIL;Lo;0;L;;;;;N;;;;;
+10096;LINEAR B IDEOGRAM B131 WINE;Lo;0;L;;;;;N;;;;;
+10097;LINEAR B IDEOGRAM B132;Lo;0;L;;;;;N;;;;;
+10098;LINEAR B MONOGRAM B133 AREPA;Lo;0;L;;;;;N;;;;;
+10099;LINEAR B MONOGRAM B135 MERI;Lo;0;L;;;;;N;;;;;
+1009A;LINEAR B IDEOGRAM B140 BRONZE;Lo;0;L;;;;;N;;;;;
+1009B;LINEAR B IDEOGRAM B141 GOLD;Lo;0;L;;;;;N;;;;;
+1009C;LINEAR B IDEOGRAM B142;Lo;0;L;;;;;N;;;;;
+1009D;LINEAR B IDEOGRAM B145 WOOL;Lo;0;L;;;;;N;;;;;
+1009E;LINEAR B IDEOGRAM B146;Lo;0;L;;;;;N;;;;;
+1009F;LINEAR B IDEOGRAM B150;Lo;0;L;;;;;N;;;;;
+100A0;LINEAR B IDEOGRAM B151 HORN;Lo;0;L;;;;;N;;;;;
+100A1;LINEAR B IDEOGRAM B152;Lo;0;L;;;;;N;;;;;
+100A2;LINEAR B IDEOGRAM B153;Lo;0;L;;;;;N;;;;;
+100A3;LINEAR B IDEOGRAM B154;Lo;0;L;;;;;N;;;;;
+100A4;LINEAR B MONOGRAM B156 TURO2;Lo;0;L;;;;;N;;;;;
+100A5;LINEAR B IDEOGRAM B157;Lo;0;L;;;;;N;;;;;
+100A6;LINEAR B IDEOGRAM B158;Lo;0;L;;;;;N;;;;;
+100A7;LINEAR B IDEOGRAM B159 CLOTH;Lo;0;L;;;;;N;;;;;
+100A8;LINEAR B IDEOGRAM B160;Lo;0;L;;;;;N;;;;;
+100A9;LINEAR B IDEOGRAM B161;Lo;0;L;;;;;N;;;;;
+100AA;LINEAR B IDEOGRAM B162 GARMENT;Lo;0;L;;;;;N;;;;;
+100AB;LINEAR B IDEOGRAM B163 ARMOUR;Lo;0;L;;;;;N;;;;;
+100AC;LINEAR B IDEOGRAM B164;Lo;0;L;;;;;N;;;;;
+100AD;LINEAR B IDEOGRAM B165;Lo;0;L;;;;;N;;;;;
+100AE;LINEAR B IDEOGRAM B166;Lo;0;L;;;;;N;;;;;
+100AF;LINEAR B IDEOGRAM B167;Lo;0;L;;;;;N;;;;;
+100B0;LINEAR B IDEOGRAM B168;Lo;0;L;;;;;N;;;;;
+100B1;LINEAR B IDEOGRAM B169;Lo;0;L;;;;;N;;;;;
+100B2;LINEAR B IDEOGRAM B170;Lo;0;L;;;;;N;;;;;
+100B3;LINEAR B IDEOGRAM B171;Lo;0;L;;;;;N;;;;;
+100B4;LINEAR B IDEOGRAM B172;Lo;0;L;;;;;N;;;;;
+100B5;LINEAR B IDEOGRAM B173 MONTH;Lo;0;L;;;;;N;;;;;
+100B6;LINEAR B IDEOGRAM B174;Lo;0;L;;;;;N;;;;;
+100B7;LINEAR B IDEOGRAM B176 TREE;Lo;0;L;;;;;N;;;;;
+100B8;LINEAR B IDEOGRAM B177;Lo;0;L;;;;;N;;;;;
+100B9;LINEAR B IDEOGRAM B178;Lo;0;L;;;;;N;;;;;
+100BA;LINEAR B IDEOGRAM B179;Lo;0;L;;;;;N;;;;;
+100BB;LINEAR B IDEOGRAM B180;Lo;0;L;;;;;N;;;;;
+100BC;LINEAR B IDEOGRAM B181;Lo;0;L;;;;;N;;;;;
+100BD;LINEAR B IDEOGRAM B182;Lo;0;L;;;;;N;;;;;
+100BE;LINEAR B IDEOGRAM B183;Lo;0;L;;;;;N;;;;;
+100BF;LINEAR B IDEOGRAM B184;Lo;0;L;;;;;N;;;;;
+100C0;LINEAR B IDEOGRAM B185;Lo;0;L;;;;;N;;;;;
+100C1;LINEAR B IDEOGRAM B189;Lo;0;L;;;;;N;;;;;
+100C2;LINEAR B IDEOGRAM B190;Lo;0;L;;;;;N;;;;;
+100C3;LINEAR B IDEOGRAM B191 HELMET;Lo;0;L;;;;;N;;;;;
+100C4;LINEAR B IDEOGRAM B220 FOOTSTOOL;Lo;0;L;;;;;N;;;;;
+100C5;LINEAR B IDEOGRAM B225 BATHTUB;Lo;0;L;;;;;N;;;;;
+100C6;LINEAR B IDEOGRAM B230 SPEAR;Lo;0;L;;;;;N;;;;;
+100C7;LINEAR B IDEOGRAM B231 ARROW;Lo;0;L;;;;;N;;;;;
+100C8;LINEAR B IDEOGRAM B232;Lo;0;L;;;;;N;;;;;
+100C9;LINEAR B IDEOGRAM B233 SWORD;Lo;0;L;;;;;N;;;;;
+100CA;LINEAR B IDEOGRAM B234;Lo;0;L;;;;;N;;;;;
+100CB;LINEAR B IDEOGRAM B236;Lo;0;L;;;;;N;;;;;
+100CC;LINEAR B IDEOGRAM B240 WHEELED CHARIOT;Lo;0;L;;;;;N;;;;;
+100CD;LINEAR B IDEOGRAM B241 CHARIOT;Lo;0;L;;;;;N;;;;;
+100CE;LINEAR B IDEOGRAM B242 CHARIOT FRAME;Lo;0;L;;;;;N;;;;;
+100CF;LINEAR B IDEOGRAM B243 WHEEL;Lo;0;L;;;;;N;;;;;
+100D0;LINEAR B IDEOGRAM B245;Lo;0;L;;;;;N;;;;;
+100D1;LINEAR B IDEOGRAM B246;Lo;0;L;;;;;N;;;;;
+100D2;LINEAR B MONOGRAM B247 DIPTE;Lo;0;L;;;;;N;;;;;
+100D3;LINEAR B IDEOGRAM B248;Lo;0;L;;;;;N;;;;;
+100D4;LINEAR B IDEOGRAM B249;Lo;0;L;;;;;N;;;;;
+100D5;LINEAR B IDEOGRAM B251;Lo;0;L;;;;;N;;;;;
+100D6;LINEAR B IDEOGRAM B252;Lo;0;L;;;;;N;;;;;
+100D7;LINEAR B IDEOGRAM B253;Lo;0;L;;;;;N;;;;;
+100D8;LINEAR B IDEOGRAM B254 DART;Lo;0;L;;;;;N;;;;;
+100D9;LINEAR B IDEOGRAM B255;Lo;0;L;;;;;N;;;;;
+100DA;LINEAR B IDEOGRAM B256;Lo;0;L;;;;;N;;;;;
+100DB;LINEAR B IDEOGRAM B257;Lo;0;L;;;;;N;;;;;
+100DC;LINEAR B IDEOGRAM B258;Lo;0;L;;;;;N;;;;;
+100DD;LINEAR B IDEOGRAM B259;Lo;0;L;;;;;N;;;;;
+100DE;LINEAR B IDEOGRAM VESSEL B155;Lo;0;L;;;;;N;;;;;
+100DF;LINEAR B IDEOGRAM VESSEL B200;Lo;0;L;;;;;N;;;;;
+100E0;LINEAR B IDEOGRAM VESSEL B201;Lo;0;L;;;;;N;;;;;
+100E1;LINEAR B IDEOGRAM VESSEL B202;Lo;0;L;;;;;N;;;;;
+100E2;LINEAR B IDEOGRAM VESSEL B203;Lo;0;L;;;;;N;;;;;
+100E3;LINEAR B IDEOGRAM VESSEL B204;Lo;0;L;;;;;N;;;;;
+100E4;LINEAR B IDEOGRAM VESSEL B205;Lo;0;L;;;;;N;;;;;
+100E5;LINEAR B IDEOGRAM VESSEL B206;Lo;0;L;;;;;N;;;;;
+100E6;LINEAR B IDEOGRAM VESSEL B207;Lo;0;L;;;;;N;;;;;
+100E7;LINEAR B IDEOGRAM VESSEL B208;Lo;0;L;;;;;N;;;;;
+100E8;LINEAR B IDEOGRAM VESSEL B209;Lo;0;L;;;;;N;;;;;
+100E9;LINEAR B IDEOGRAM VESSEL B210;Lo;0;L;;;;;N;;;;;
+100EA;LINEAR B IDEOGRAM VESSEL B211;Lo;0;L;;;;;N;;;;;
+100EB;LINEAR B IDEOGRAM VESSEL B212;Lo;0;L;;;;;N;;;;;
+100EC;LINEAR B IDEOGRAM VESSEL B213;Lo;0;L;;;;;N;;;;;
+100ED;LINEAR B IDEOGRAM VESSEL B214;Lo;0;L;;;;;N;;;;;
+100EE;LINEAR B IDEOGRAM VESSEL B215;Lo;0;L;;;;;N;;;;;
+100EF;LINEAR B IDEOGRAM VESSEL B216;Lo;0;L;;;;;N;;;;;
+100F0;LINEAR B IDEOGRAM VESSEL B217;Lo;0;L;;;;;N;;;;;
+100F1;LINEAR B IDEOGRAM VESSEL B218;Lo;0;L;;;;;N;;;;;
+100F2;LINEAR B IDEOGRAM VESSEL B219;Lo;0;L;;;;;N;;;;;
+100F3;LINEAR B IDEOGRAM VESSEL B221;Lo;0;L;;;;;N;;;;;
+100F4;LINEAR B IDEOGRAM VESSEL B222;Lo;0;L;;;;;N;;;;;
+100F5;LINEAR B IDEOGRAM VESSEL B226;Lo;0;L;;;;;N;;;;;
+100F6;LINEAR B IDEOGRAM VESSEL B227;Lo;0;L;;;;;N;;;;;
+100F7;LINEAR B IDEOGRAM VESSEL B228;Lo;0;L;;;;;N;;;;;
+100F8;LINEAR B IDEOGRAM VESSEL B229;Lo;0;L;;;;;N;;;;;
+100F9;LINEAR B IDEOGRAM VESSEL B250;Lo;0;L;;;;;N;;;;;
+100FA;LINEAR B IDEOGRAM VESSEL B305;Lo;0;L;;;;;N;;;;;
+10100;AEGEAN WORD SEPARATOR LINE;Po;0;L;;;;;N;;;;;
+10101;AEGEAN WORD SEPARATOR DOT;Po;0;ON;;;;;N;;;;;
+10102;AEGEAN CHECK MARK;So;0;L;;;;;N;;;;;
+10107;AEGEAN NUMBER ONE;No;0;L;;;;1;N;;;;;
+10108;AEGEAN NUMBER TWO;No;0;L;;;;2;N;;;;;
+10109;AEGEAN NUMBER THREE;No;0;L;;;;3;N;;;;;
+1010A;AEGEAN NUMBER FOUR;No;0;L;;;;4;N;;;;;
+1010B;AEGEAN NUMBER FIVE;No;0;L;;;;5;N;;;;;
+1010C;AEGEAN NUMBER SIX;No;0;L;;;;6;N;;;;;
+1010D;AEGEAN NUMBER SEVEN;No;0;L;;;;7;N;;;;;
+1010E;AEGEAN NUMBER EIGHT;No;0;L;;;;8;N;;;;;
+1010F;AEGEAN NUMBER NINE;No;0;L;;;;9;N;;;;;
+10110;AEGEAN NUMBER TEN;No;0;L;;;;10;N;;;;;
+10111;AEGEAN NUMBER TWENTY;No;0;L;;;;20;N;;;;;
+10112;AEGEAN NUMBER THIRTY;No;0;L;;;;30;N;;;;;
+10113;AEGEAN NUMBER FORTY;No;0;L;;;;40;N;;;;;
+10114;AEGEAN NUMBER FIFTY;No;0;L;;;;50;N;;;;;
+10115;AEGEAN NUMBER SIXTY;No;0;L;;;;60;N;;;;;
+10116;AEGEAN NUMBER SEVENTY;No;0;L;;;;70;N;;;;;
+10117;AEGEAN NUMBER EIGHTY;No;0;L;;;;80;N;;;;;
+10118;AEGEAN NUMBER NINETY;No;0;L;;;;90;N;;;;;
+10119;AEGEAN NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;;
+1011A;AEGEAN NUMBER TWO HUNDRED;No;0;L;;;;200;N;;;;;
+1011B;AEGEAN NUMBER THREE HUNDRED;No;0;L;;;;300;N;;;;;
+1011C;AEGEAN NUMBER FOUR HUNDRED;No;0;L;;;;400;N;;;;;
+1011D;AEGEAN NUMBER FIVE HUNDRED;No;0;L;;;;500;N;;;;;
+1011E;AEGEAN NUMBER SIX HUNDRED;No;0;L;;;;600;N;;;;;
+1011F;AEGEAN NUMBER SEVEN HUNDRED;No;0;L;;;;700;N;;;;;
+10120;AEGEAN NUMBER EIGHT HUNDRED;No;0;L;;;;800;N;;;;;
+10121;AEGEAN NUMBER NINE HUNDRED;No;0;L;;;;900;N;;;;;
+10122;AEGEAN NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;;
+10123;AEGEAN NUMBER TWO THOUSAND;No;0;L;;;;2000;N;;;;;
+10124;AEGEAN NUMBER THREE THOUSAND;No;0;L;;;;3000;N;;;;;
+10125;AEGEAN NUMBER FOUR THOUSAND;No;0;L;;;;4000;N;;;;;
+10126;AEGEAN NUMBER FIVE THOUSAND;No;0;L;;;;5000;N;;;;;
+10127;AEGEAN NUMBER SIX THOUSAND;No;0;L;;;;6000;N;;;;;
+10128;AEGEAN NUMBER SEVEN THOUSAND;No;0;L;;;;7000;N;;;;;
+10129;AEGEAN NUMBER EIGHT THOUSAND;No;0;L;;;;8000;N;;;;;
+1012A;AEGEAN NUMBER NINE THOUSAND;No;0;L;;;;9000;N;;;;;
+1012B;AEGEAN NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;;
+1012C;AEGEAN NUMBER TWENTY THOUSAND;No;0;L;;;;20000;N;;;;;
+1012D;AEGEAN NUMBER THIRTY THOUSAND;No;0;L;;;;30000;N;;;;;
+1012E;AEGEAN NUMBER FORTY THOUSAND;No;0;L;;;;40000;N;;;;;
+1012F;AEGEAN NUMBER FIFTY THOUSAND;No;0;L;;;;50000;N;;;;;
+10130;AEGEAN NUMBER SIXTY THOUSAND;No;0;L;;;;60000;N;;;;;
+10131;AEGEAN NUMBER SEVENTY THOUSAND;No;0;L;;;;70000;N;;;;;
+10132;AEGEAN NUMBER EIGHTY THOUSAND;No;0;L;;;;80000;N;;;;;
+10133;AEGEAN NUMBER NINETY THOUSAND;No;0;L;;;;90000;N;;;;;
+10137;AEGEAN WEIGHT BASE UNIT;So;0;L;;;;;N;;;;;
+10138;AEGEAN WEIGHT FIRST SUBUNIT;So;0;L;;;;;N;;;;;
+10139;AEGEAN WEIGHT SECOND SUBUNIT;So;0;L;;;;;N;;;;;
+1013A;AEGEAN WEIGHT THIRD SUBUNIT;So;0;L;;;;;N;;;;;
+1013B;AEGEAN WEIGHT FOURTH SUBUNIT;So;0;L;;;;;N;;;;;
+1013C;AEGEAN DRY MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;;
+1013D;AEGEAN LIQUID MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;;
+1013E;AEGEAN MEASURE SECOND SUBUNIT;So;0;L;;;;;N;;;;;
+1013F;AEGEAN MEASURE THIRD SUBUNIT;So;0;L;;;;;N;;;;;
+10140;GREEK ACROPHONIC ATTIC ONE QUARTER;Nl;0;ON;;;;1/4;N;;;;;
+10141;GREEK ACROPHONIC ATTIC ONE HALF;Nl;0;ON;;;;1/2;N;;;;;
+10142;GREEK ACROPHONIC ATTIC ONE DRACHMA;Nl;0;ON;;;;1;N;;;;;
+10143;GREEK ACROPHONIC ATTIC FIVE;Nl;0;ON;;;;5;N;;;;;
+10144;GREEK ACROPHONIC ATTIC FIFTY;Nl;0;ON;;;;50;N;;;;;
+10145;GREEK ACROPHONIC ATTIC FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
+10146;GREEK ACROPHONIC ATTIC FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;;
+10147;GREEK ACROPHONIC ATTIC FIFTY THOUSAND;Nl;0;ON;;;;50000;N;;;;;
+10148;GREEK ACROPHONIC ATTIC FIVE TALENTS;Nl;0;ON;;;;5;N;;;;;
+10149;GREEK ACROPHONIC ATTIC TEN TALENTS;Nl;0;ON;;;;10;N;;;;;
+1014A;GREEK ACROPHONIC ATTIC FIFTY TALENTS;Nl;0;ON;;;;50;N;;;;;
+1014B;GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS;Nl;0;ON;;;;100;N;;;;;
+1014C;GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS;Nl;0;ON;;;;500;N;;;;;
+1014D;GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS;Nl;0;ON;;;;1000;N;;;;;
+1014E;GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS;Nl;0;ON;;;;5000;N;;;;;
+1014F;GREEK ACROPHONIC ATTIC FIVE STATERS;Nl;0;ON;;;;5;N;;;;;
+10150;GREEK ACROPHONIC ATTIC TEN STATERS;Nl;0;ON;;;;10;N;;;;;
+10151;GREEK ACROPHONIC ATTIC FIFTY STATERS;Nl;0;ON;;;;50;N;;;;;
+10152;GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS;Nl;0;ON;;;;100;N;;;;;
+10153;GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS;Nl;0;ON;;;;500;N;;;;;
+10154;GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS;Nl;0;ON;;;;1000;N;;;;;
+10155;GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS;Nl;0;ON;;;;10000;N;;;;;
+10156;GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS;Nl;0;ON;;;;50000;N;;;;;
+10157;GREEK ACROPHONIC ATTIC TEN MNAS;Nl;0;ON;;;;10;N;;;;;
+10158;GREEK ACROPHONIC HERAEUM ONE PLETHRON;Nl;0;ON;;;;1;N;;;;;
+10159;GREEK ACROPHONIC THESPIAN ONE;Nl;0;ON;;;;1;N;;;;;
+1015A;GREEK ACROPHONIC HERMIONIAN ONE;Nl;0;ON;;;;1;N;;;;;
+1015B;GREEK ACROPHONIC EPIDAUREAN TWO;Nl;0;ON;;;;2;N;;;;;
+1015C;GREEK ACROPHONIC THESPIAN TWO;Nl;0;ON;;;;2;N;;;;;
+1015D;GREEK ACROPHONIC CYRENAIC TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;;
+1015E;GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;;
+1015F;GREEK ACROPHONIC TROEZENIAN FIVE;Nl;0;ON;;;;5;N;;;;;
+10160;GREEK ACROPHONIC TROEZENIAN TEN;Nl;0;ON;;;;10;N;;;;;
+10161;GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM;Nl;0;ON;;;;10;N;;;;;
+10162;GREEK ACROPHONIC HERMIONIAN TEN;Nl;0;ON;;;;10;N;;;;;
+10163;GREEK ACROPHONIC MESSENIAN TEN;Nl;0;ON;;;;10;N;;;;;
+10164;GREEK ACROPHONIC THESPIAN TEN;Nl;0;ON;;;;10;N;;;;;
+10165;GREEK ACROPHONIC THESPIAN THIRTY;Nl;0;ON;;;;30;N;;;;;
+10166;GREEK ACROPHONIC TROEZENIAN FIFTY;Nl;0;ON;;;;50;N;;;;;
+10167;GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM;Nl;0;ON;;;;50;N;;;;;
+10168;GREEK ACROPHONIC HERMIONIAN FIFTY;Nl;0;ON;;;;50;N;;;;;
+10169;GREEK ACROPHONIC THESPIAN FIFTY;Nl;0;ON;;;;50;N;;;;;
+1016A;GREEK ACROPHONIC THESPIAN ONE HUNDRED;Nl;0;ON;;;;100;N;;;;;
+1016B;GREEK ACROPHONIC THESPIAN THREE HUNDRED;Nl;0;ON;;;;300;N;;;;;
+1016C;GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
+1016D;GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
+1016E;GREEK ACROPHONIC THESPIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
+1016F;GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
+10170;GREEK ACROPHONIC NAXIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;;
+10171;GREEK ACROPHONIC THESPIAN ONE THOUSAND;Nl;0;ON;;;;1000;N;;;;;
+10172;GREEK ACROPHONIC THESPIAN FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;;
+10173;GREEK ACROPHONIC DELPHIC FIVE MNAS;Nl;0;ON;;;;5;N;;;;;
+10174;GREEK ACROPHONIC STRATIAN FIFTY MNAS;Nl;0;ON;;;;50;N;;;;;
+10175;GREEK ONE HALF SIGN;No;0;ON;;;;1/2;N;;;;;
+10176;GREEK ONE HALF SIGN ALTERNATE FORM;No;0;ON;;;;1/2;N;;;;;
+10177;GREEK TWO THIRDS SIGN;No;0;ON;;;;2/3;N;;;;;
+10178;GREEK THREE QUARTERS SIGN;No;0;ON;;;;3/4;N;;;;;
+10179;GREEK YEAR SIGN;So;0;ON;;;;;N;;;;;
+1017A;GREEK TALENT SIGN;So;0;ON;;;;;N;;;;;
+1017B;GREEK DRACHMA SIGN;So;0;ON;;;;;N;;;;;
+1017C;GREEK OBOL SIGN;So;0;ON;;;;;N;;;;;
+1017D;GREEK TWO OBOLS SIGN;So;0;ON;;;;;N;;;;;
+1017E;GREEK THREE OBOLS SIGN;So;0;ON;;;;;N;;;;;
+1017F;GREEK FOUR OBOLS SIGN;So;0;ON;;;;;N;;;;;
+10180;GREEK FIVE OBOLS SIGN;So;0;ON;;;;;N;;;;;
+10181;GREEK METRETES SIGN;So;0;ON;;;;;N;;;;;
+10182;GREEK KYATHOS BASE SIGN;So;0;ON;;;;;N;;;;;
+10183;GREEK LITRA SIGN;So;0;ON;;;;;N;;;;;
+10184;GREEK OUNKIA SIGN;So;0;ON;;;;;N;;;;;
+10185;GREEK XESTES SIGN;So;0;ON;;;;;N;;;;;
+10186;GREEK ARTABE SIGN;So;0;ON;;;;;N;;;;;
+10187;GREEK AROURA SIGN;So;0;ON;;;;;N;;;;;
+10188;GREEK GRAMMA SIGN;So;0;ON;;;;;N;;;;;
+10189;GREEK TRYBLION BASE SIGN;So;0;ON;;;;;N;;;;;
+1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;;
+10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;;
+10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;;
+10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;;
+10193;ROMAN SEXTULA SIGN;So;0;ON;;;;;N;;;;;
+10194;ROMAN DIMIDIA SEXTULA SIGN;So;0;ON;;;;;N;;;;;
+10195;ROMAN SILIQUA SIGN;So;0;ON;;;;;N;;;;;
+10196;ROMAN DENARIUS SIGN;So;0;ON;;;;;N;;;;;
+10197;ROMAN QUINARIUS SIGN;So;0;ON;;;;;N;;;;;
+10198;ROMAN SESTERTIUS SIGN;So;0;ON;;;;;N;;;;;
+10199;ROMAN DUPONDIUS SIGN;So;0;ON;;;;;N;;;;;
+1019A;ROMAN AS SIGN;So;0;ON;;;;;N;;;;;
+1019B;ROMAN CENTURIAL SIGN;So;0;ON;;;;;N;;;;;
+101D0;PHAISTOS DISC SIGN PEDESTRIAN;So;0;L;;;;;N;;;;;
+101D1;PHAISTOS DISC SIGN PLUMED HEAD;So;0;L;;;;;N;;;;;
+101D2;PHAISTOS DISC SIGN TATTOOED HEAD;So;0;L;;;;;N;;;;;
+101D3;PHAISTOS DISC SIGN CAPTIVE;So;0;L;;;;;N;;;;;
+101D4;PHAISTOS DISC SIGN CHILD;So;0;L;;;;;N;;;;;
+101D5;PHAISTOS DISC SIGN WOMAN;So;0;L;;;;;N;;;;;
+101D6;PHAISTOS DISC SIGN HELMET;So;0;L;;;;;N;;;;;
+101D7;PHAISTOS DISC SIGN GAUNTLET;So;0;L;;;;;N;;;;;
+101D8;PHAISTOS DISC SIGN TIARA;So;0;L;;;;;N;;;;;
+101D9;PHAISTOS DISC SIGN ARROW;So;0;L;;;;;N;;;;;
+101DA;PHAISTOS DISC SIGN BOW;So;0;L;;;;;N;;;;;
+101DB;PHAISTOS DISC SIGN SHIELD;So;0;L;;;;;N;;;;;
+101DC;PHAISTOS DISC SIGN CLUB;So;0;L;;;;;N;;;;;
+101DD;PHAISTOS DISC SIGN MANACLES;So;0;L;;;;;N;;;;;
+101DE;PHAISTOS DISC SIGN MATTOCK;So;0;L;;;;;N;;;;;
+101DF;PHAISTOS DISC SIGN SAW;So;0;L;;;;;N;;;;;
+101E0;PHAISTOS DISC SIGN LID;So;0;L;;;;;N;;;;;
+101E1;PHAISTOS DISC SIGN BOOMERANG;So;0;L;;;;;N;;;;;
+101E2;PHAISTOS DISC SIGN CARPENTRY PLANE;So;0;L;;;;;N;;;;;
+101E3;PHAISTOS DISC SIGN DOLIUM;So;0;L;;;;;N;;;;;
+101E4;PHAISTOS DISC SIGN COMB;So;0;L;;;;;N;;;;;
+101E5;PHAISTOS DISC SIGN SLING;So;0;L;;;;;N;;;;;
+101E6;PHAISTOS DISC SIGN COLUMN;So;0;L;;;;;N;;;;;
+101E7;PHAISTOS DISC SIGN BEEHIVE;So;0;L;;;;;N;;;;;
+101E8;PHAISTOS DISC SIGN SHIP;So;0;L;;;;;N;;;;;
+101E9;PHAISTOS DISC SIGN HORN;So;0;L;;;;;N;;;;;
+101EA;PHAISTOS DISC SIGN HIDE;So;0;L;;;;;N;;;;;
+101EB;PHAISTOS DISC SIGN BULLS LEG;So;0;L;;;;;N;;;;;
+101EC;PHAISTOS DISC SIGN CAT;So;0;L;;;;;N;;;;;
+101ED;PHAISTOS DISC SIGN RAM;So;0;L;;;;;N;;;;;
+101EE;PHAISTOS DISC SIGN EAGLE;So;0;L;;;;;N;;;;;
+101EF;PHAISTOS DISC SIGN DOVE;So;0;L;;;;;N;;;;;
+101F0;PHAISTOS DISC SIGN TUNNY;So;0;L;;;;;N;;;;;
+101F1;PHAISTOS DISC SIGN BEE;So;0;L;;;;;N;;;;;
+101F2;PHAISTOS DISC SIGN PLANE TREE;So;0;L;;;;;N;;;;;
+101F3;PHAISTOS DISC SIGN VINE;So;0;L;;;;;N;;;;;
+101F4;PHAISTOS DISC SIGN PAPYRUS;So;0;L;;;;;N;;;;;
+101F5;PHAISTOS DISC SIGN ROSETTE;So;0;L;;;;;N;;;;;
+101F6;PHAISTOS DISC SIGN LILY;So;0;L;;;;;N;;;;;
+101F7;PHAISTOS DISC SIGN OX BACK;So;0;L;;;;;N;;;;;
+101F8;PHAISTOS DISC SIGN FLUTE;So;0;L;;;;;N;;;;;
+101F9;PHAISTOS DISC SIGN GRATER;So;0;L;;;;;N;;;;;
+101FA;PHAISTOS DISC SIGN STRAINER;So;0;L;;;;;N;;;;;
+101FB;PHAISTOS DISC SIGN SMALL AXE;So;0;L;;;;;N;;;;;
+101FC;PHAISTOS DISC SIGN WAVY BAND;So;0;L;;;;;N;;;;;
+101FD;PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE;Mn;220;NSM;;;;;N;;;;;
+10280;LYCIAN LETTER A;Lo;0;L;;;;;N;;;;;
+10281;LYCIAN LETTER E;Lo;0;L;;;;;N;;;;;
+10282;LYCIAN LETTER B;Lo;0;L;;;;;N;;;;;
+10283;LYCIAN LETTER BH;Lo;0;L;;;;;N;;;;;
+10284;LYCIAN LETTER G;Lo;0;L;;;;;N;;;;;
+10285;LYCIAN LETTER D;Lo;0;L;;;;;N;;;;;
+10286;LYCIAN LETTER I;Lo;0;L;;;;;N;;;;;
+10287;LYCIAN LETTER W;Lo;0;L;;;;;N;;;;;
+10288;LYCIAN LETTER Z;Lo;0;L;;;;;N;;;;;
+10289;LYCIAN LETTER TH;Lo;0;L;;;;;N;;;;;
+1028A;LYCIAN LETTER J;Lo;0;L;;;;;N;;;;;
+1028B;LYCIAN LETTER K;Lo;0;L;;;;;N;;;;;
+1028C;LYCIAN LETTER Q;Lo;0;L;;;;;N;;;;;
+1028D;LYCIAN LETTER L;Lo;0;L;;;;;N;;;;;
+1028E;LYCIAN LETTER M;Lo;0;L;;;;;N;;;;;
+1028F;LYCIAN LETTER N;Lo;0;L;;;;;N;;;;;
+10290;LYCIAN LETTER MM;Lo;0;L;;;;;N;;;;;
+10291;LYCIAN LETTER NN;Lo;0;L;;;;;N;;;;;
+10292;LYCIAN LETTER U;Lo;0;L;;;;;N;;;;;
+10293;LYCIAN LETTER P;Lo;0;L;;;;;N;;;;;
+10294;LYCIAN LETTER KK;Lo;0;L;;;;;N;;;;;
+10295;LYCIAN LETTER R;Lo;0;L;;;;;N;;;;;
+10296;LYCIAN LETTER S;Lo;0;L;;;;;N;;;;;
+10297;LYCIAN LETTER T;Lo;0;L;;;;;N;;;;;
+10298;LYCIAN LETTER TT;Lo;0;L;;;;;N;;;;;
+10299;LYCIAN LETTER AN;Lo;0;L;;;;;N;;;;;
+1029A;LYCIAN LETTER EN;Lo;0;L;;;;;N;;;;;
+1029B;LYCIAN LETTER H;Lo;0;L;;;;;N;;;;;
+1029C;LYCIAN LETTER X;Lo;0;L;;;;;N;;;;;
+102A0;CARIAN LETTER A;Lo;0;L;;;;;N;;;;;
+102A1;CARIAN LETTER P2;Lo;0;L;;;;;N;;;;;
+102A2;CARIAN LETTER D;Lo;0;L;;;;;N;;;;;
+102A3;CARIAN LETTER L;Lo;0;L;;;;;N;;;;;
+102A4;CARIAN LETTER UUU;Lo;0;L;;;;;N;;;;;
+102A5;CARIAN LETTER R;Lo;0;L;;;;;N;;;;;
+102A6;CARIAN LETTER LD;Lo;0;L;;;;;N;;;;;
+102A7;CARIAN LETTER A2;Lo;0;L;;;;;N;;;;;
+102A8;CARIAN LETTER Q;Lo;0;L;;;;;N;;;;;
+102A9;CARIAN LETTER B;Lo;0;L;;;;;N;;;;;
+102AA;CARIAN LETTER M;Lo;0;L;;;;;N;;;;;
+102AB;CARIAN LETTER O;Lo;0;L;;;;;N;;;;;
+102AC;CARIAN LETTER D2;Lo;0;L;;;;;N;;;;;
+102AD;CARIAN LETTER T;Lo;0;L;;;;;N;;;;;
+102AE;CARIAN LETTER SH;Lo;0;L;;;;;N;;;;;
+102AF;CARIAN LETTER SH2;Lo;0;L;;;;;N;;;;;
+102B0;CARIAN LETTER S;Lo;0;L;;;;;N;;;;;
+102B1;CARIAN LETTER C-18;Lo;0;L;;;;;N;;;;;
+102B2;CARIAN LETTER U;Lo;0;L;;;;;N;;;;;
+102B3;CARIAN LETTER NN;Lo;0;L;;;;;N;;;;;
+102B4;CARIAN LETTER X;Lo;0;L;;;;;N;;;;;
+102B5;CARIAN LETTER N;Lo;0;L;;;;;N;;;;;
+102B6;CARIAN LETTER TT2;Lo;0;L;;;;;N;;;;;
+102B7;CARIAN LETTER P;Lo;0;L;;;;;N;;;;;
+102B8;CARIAN LETTER SS;Lo;0;L;;;;;N;;;;;
+102B9;CARIAN LETTER I;Lo;0;L;;;;;N;;;;;
+102BA;CARIAN LETTER E;Lo;0;L;;;;;N;;;;;
+102BB;CARIAN LETTER UUUU;Lo;0;L;;;;;N;;;;;
+102BC;CARIAN LETTER K;Lo;0;L;;;;;N;;;;;
+102BD;CARIAN LETTER K2;Lo;0;L;;;;;N;;;;;
+102BE;CARIAN LETTER ND;Lo;0;L;;;;;N;;;;;
+102BF;CARIAN LETTER UU;Lo;0;L;;;;;N;;;;;
+102C0;CARIAN LETTER G;Lo;0;L;;;;;N;;;;;
+102C1;CARIAN LETTER G2;Lo;0;L;;;;;N;;;;;
+102C2;CARIAN LETTER ST;Lo;0;L;;;;;N;;;;;
+102C3;CARIAN LETTER ST2;Lo;0;L;;;;;N;;;;;
+102C4;CARIAN LETTER NG;Lo;0;L;;;;;N;;;;;
+102C5;CARIAN LETTER II;Lo;0;L;;;;;N;;;;;
+102C6;CARIAN LETTER C-39;Lo;0;L;;;;;N;;;;;
+102C7;CARIAN LETTER TT;Lo;0;L;;;;;N;;;;;
+102C8;CARIAN LETTER UUU2;Lo;0;L;;;;;N;;;;;
+102C9;CARIAN LETTER RR;Lo;0;L;;;;;N;;;;;
+102CA;CARIAN LETTER MB;Lo;0;L;;;;;N;;;;;
+102CB;CARIAN LETTER MB2;Lo;0;L;;;;;N;;;;;
+102CC;CARIAN LETTER MB3;Lo;0;L;;;;;N;;;;;
+102CD;CARIAN LETTER MB4;Lo;0;L;;;;;N;;;;;
+102CE;CARIAN LETTER LD2;Lo;0;L;;;;;N;;;;;
+102CF;CARIAN LETTER E2;Lo;0;L;;;;;N;;;;;
+102D0;CARIAN LETTER UUU3;Lo;0;L;;;;;N;;;;;
+10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;;
+10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;;
+10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;;
+10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;;
+10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;;
+10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;;
+10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;;
+10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;;
+10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;;
+10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;;
+1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;;
+1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;;
+1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;;
+1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;;
+1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;;
+1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;;;;
+10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;;
+10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;;
+10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;;
+10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;;
+10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;;
+10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;;
+10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;;
+10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;;;;
+10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;;
+10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;;
+1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;;
+1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;;;;
+1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;;;;
+1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;;;;
+1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;;;;
+10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;;
+10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;;
+10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;;
+10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;;
+10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;;
+10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;;
+10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;;
+10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;;
+10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;;
+10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;;
+10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;;
+10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;;
+10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;;
+10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;;
+1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;;
+1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;;
+1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;;
+1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;;
+1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;;
+1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;;
+10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;;
+10341;GOTHIC LETTER NINETY;Nl;0;L;;;;90;N;;;;;
+10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;;
+10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;;
+10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;;
+10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;;
+10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;;
+10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;;
+10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;;
+10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;;
+1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;900;N;;;;;
+10380;UGARITIC LETTER ALPA;Lo;0;L;;;;;N;;;;;
+10381;UGARITIC LETTER BETA;Lo;0;L;;;;;N;;;;;
+10382;UGARITIC LETTER GAMLA;Lo;0;L;;;;;N;;;;;
+10383;UGARITIC LETTER KHA;Lo;0;L;;;;;N;;;;;
+10384;UGARITIC LETTER DELTA;Lo;0;L;;;;;N;;;;;
+10385;UGARITIC LETTER HO;Lo;0;L;;;;;N;;;;;
+10386;UGARITIC LETTER WO;Lo;0;L;;;;;N;;;;;
+10387;UGARITIC LETTER ZETA;Lo;0;L;;;;;N;;;;;
+10388;UGARITIC LETTER HOTA;Lo;0;L;;;;;N;;;;;
+10389;UGARITIC LETTER TET;Lo;0;L;;;;;N;;;;;
+1038A;UGARITIC LETTER YOD;Lo;0;L;;;;;N;;;;;
+1038B;UGARITIC LETTER KAF;Lo;0;L;;;;;N;;;;;
+1038C;UGARITIC LETTER SHIN;Lo;0;L;;;;;N;;;;;
+1038D;UGARITIC LETTER LAMDA;Lo;0;L;;;;;N;;;;;
+1038E;UGARITIC LETTER MEM;Lo;0;L;;;;;N;;;;;
+1038F;UGARITIC LETTER DHAL;Lo;0;L;;;;;N;;;;;
+10390;UGARITIC LETTER NUN;Lo;0;L;;;;;N;;;;;
+10391;UGARITIC LETTER ZU;Lo;0;L;;;;;N;;;;;
+10392;UGARITIC LETTER SAMKA;Lo;0;L;;;;;N;;;;;
+10393;UGARITIC LETTER AIN;Lo;0;L;;;;;N;;;;;
+10394;UGARITIC LETTER PU;Lo;0;L;;;;;N;;;;;
+10395;UGARITIC LETTER SADE;Lo;0;L;;;;;N;;;;;
+10396;UGARITIC LETTER QOPA;Lo;0;L;;;;;N;;;;;
+10397;UGARITIC LETTER RASHA;Lo;0;L;;;;;N;;;;;
+10398;UGARITIC LETTER THANNA;Lo;0;L;;;;;N;;;;;
+10399;UGARITIC LETTER GHAIN;Lo;0;L;;;;;N;;;;;
+1039A;UGARITIC LETTER TO;Lo;0;L;;;;;N;;;;;
+1039B;UGARITIC LETTER I;Lo;0;L;;;;;N;;;;;
+1039C;UGARITIC LETTER U;Lo;0;L;;;;;N;;;;;
+1039D;UGARITIC LETTER SSU;Lo;0;L;;;;;N;;;;;
+1039F;UGARITIC WORD DIVIDER;Po;0;L;;;;;N;;;;;
+103A0;OLD PERSIAN SIGN A;Lo;0;L;;;;;N;;;;;
+103A1;OLD PERSIAN SIGN I;Lo;0;L;;;;;N;;;;;
+103A2;OLD PERSIAN SIGN U;Lo;0;L;;;;;N;;;;;
+103A3;OLD PERSIAN SIGN KA;Lo;0;L;;;;;N;;;;;
+103A4;OLD PERSIAN SIGN KU;Lo;0;L;;;;;N;;;;;
+103A5;OLD PERSIAN SIGN GA;Lo;0;L;;;;;N;;;;;
+103A6;OLD PERSIAN SIGN GU;Lo;0;L;;;;;N;;;;;
+103A7;OLD PERSIAN SIGN XA;Lo;0;L;;;;;N;;;;;
+103A8;OLD PERSIAN SIGN CA;Lo;0;L;;;;;N;;;;;
+103A9;OLD PERSIAN SIGN JA;Lo;0;L;;;;;N;;;;;
+103AA;OLD PERSIAN SIGN JI;Lo;0;L;;;;;N;;;;;
+103AB;OLD PERSIAN SIGN TA;Lo;0;L;;;;;N;;;;;
+103AC;OLD PERSIAN SIGN TU;Lo;0;L;;;;;N;;;;;
+103AD;OLD PERSIAN SIGN DA;Lo;0;L;;;;;N;;;;;
+103AE;OLD PERSIAN SIGN DI;Lo;0;L;;;;;N;;;;;
+103AF;OLD PERSIAN SIGN DU;Lo;0;L;;;;;N;;;;;
+103B0;OLD PERSIAN SIGN THA;Lo;0;L;;;;;N;;;;;
+103B1;OLD PERSIAN SIGN PA;Lo;0;L;;;;;N;;;;;
+103B2;OLD PERSIAN SIGN BA;Lo;0;L;;;;;N;;;;;
+103B3;OLD PERSIAN SIGN FA;Lo;0;L;;;;;N;;;;;
+103B4;OLD PERSIAN SIGN NA;Lo;0;L;;;;;N;;;;;
+103B5;OLD PERSIAN SIGN NU;Lo;0;L;;;;;N;;;;;
+103B6;OLD PERSIAN SIGN MA;Lo;0;L;;;;;N;;;;;
+103B7;OLD PERSIAN SIGN MI;Lo;0;L;;;;;N;;;;;
+103B8;OLD PERSIAN SIGN MU;Lo;0;L;;;;;N;;;;;
+103B9;OLD PERSIAN SIGN YA;Lo;0;L;;;;;N;;;;;
+103BA;OLD PERSIAN SIGN VA;Lo;0;L;;;;;N;;;;;
+103BB;OLD PERSIAN SIGN VI;Lo;0;L;;;;;N;;;;;
+103BC;OLD PERSIAN SIGN RA;Lo;0;L;;;;;N;;;;;
+103BD;OLD PERSIAN SIGN RU;Lo;0;L;;;;;N;;;;;
+103BE;OLD PERSIAN SIGN LA;Lo;0;L;;;;;N;;;;;
+103BF;OLD PERSIAN SIGN SA;Lo;0;L;;;;;N;;;;;
+103C0;OLD PERSIAN SIGN ZA;Lo;0;L;;;;;N;;;;;
+103C1;OLD PERSIAN SIGN SHA;Lo;0;L;;;;;N;;;;;
+103C2;OLD PERSIAN SIGN SSA;Lo;0;L;;;;;N;;;;;
+103C3;OLD PERSIAN SIGN HA;Lo;0;L;;;;;N;;;;;
+103C8;OLD PERSIAN SIGN AURAMAZDAA;Lo;0;L;;;;;N;;;;;
+103C9;OLD PERSIAN SIGN AURAMAZDAA-2;Lo;0;L;;;;;N;;;;;
+103CA;OLD PERSIAN SIGN AURAMAZDAAHA;Lo;0;L;;;;;N;;;;;
+103CB;OLD PERSIAN SIGN XSHAAYATHIYA;Lo;0;L;;;;;N;;;;;
+103CC;OLD PERSIAN SIGN DAHYAAUSH;Lo;0;L;;;;;N;;;;;
+103CD;OLD PERSIAN SIGN DAHYAAUSH-2;Lo;0;L;;;;;N;;;;;
+103CE;OLD PERSIAN SIGN BAGA;Lo;0;L;;;;;N;;;;;
+103CF;OLD PERSIAN SIGN BUUMISH;Lo;0;L;;;;;N;;;;;
+103D0;OLD PERSIAN WORD DIVIDER;Po;0;L;;;;;N;;;;;
+103D1;OLD PERSIAN NUMBER ONE;Nl;0;L;;;;1;N;;;;;
+103D2;OLD PERSIAN NUMBER TWO;Nl;0;L;;;;2;N;;;;;
+103D3;OLD PERSIAN NUMBER TEN;Nl;0;L;;;;10;N;;;;;
+103D4;OLD PERSIAN NUMBER TWENTY;Nl;0;L;;;;20;N;;;;;
+103D5;OLD PERSIAN NUMBER HUNDRED;Nl;0;L;;;;100;N;;;;;
+10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428;
+10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429;
+10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A;
+10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B;
+10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C;
+10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D;
+10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E;
+10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F;
+10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430;
+10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431;
+1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432;
+1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433;
+1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434;
+1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435;
+1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436;
+1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437;
+10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438;
+10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439;
+10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A;
+10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B;
+10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C;
+10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D;
+10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E;
+10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F;
+10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440;
+10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441;
+1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442;
+1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443;
+1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444;
+1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445;
+1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446;
+1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447;
+10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448;
+10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449;
+10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A;
+10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B;
+10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C;
+10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D;
+10426;DESERET CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;1044E;
+10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F;
+10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400
+10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401
+1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402
+1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403
+1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404
+1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405
+1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406
+1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407
+10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408
+10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409
+10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A
+10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B
+10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C
+10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D
+10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E
+10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F
+10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410
+10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411
+1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412
+1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413
+1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414
+1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415
+1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416
+1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417
+10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418
+10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419
+10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A
+10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B
+10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C
+10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D
+10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E
+10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F
+10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420
+10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421
+1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422
+1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423
+1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424
+1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425
+1044E;DESERET SMALL LETTER OI;Ll;0;L;;;;;N;;;10426;;10426
+1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427
+10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;;
+10451;SHAVIAN LETTER TOT;Lo;0;L;;;;;N;;;;;
+10452;SHAVIAN LETTER KICK;Lo;0;L;;;;;N;;;;;
+10453;SHAVIAN LETTER FEE;Lo;0;L;;;;;N;;;;;
+10454;SHAVIAN LETTER THIGH;Lo;0;L;;;;;N;;;;;
+10455;SHAVIAN LETTER SO;Lo;0;L;;;;;N;;;;;
+10456;SHAVIAN LETTER SURE;Lo;0;L;;;;;N;;;;;
+10457;SHAVIAN LETTER CHURCH;Lo;0;L;;;;;N;;;;;
+10458;SHAVIAN LETTER YEA;Lo;0;L;;;;;N;;;;;
+10459;SHAVIAN LETTER HUNG;Lo;0;L;;;;;N;;;;;
+1045A;SHAVIAN LETTER BIB;Lo;0;L;;;;;N;;;;;
+1045B;SHAVIAN LETTER DEAD;Lo;0;L;;;;;N;;;;;
+1045C;SHAVIAN LETTER GAG;Lo;0;L;;;;;N;;;;;
+1045D;SHAVIAN LETTER VOW;Lo;0;L;;;;;N;;;;;
+1045E;SHAVIAN LETTER THEY;Lo;0;L;;;;;N;;;;;
+1045F;SHAVIAN LETTER ZOO;Lo;0;L;;;;;N;;;;;
+10460;SHAVIAN LETTER MEASURE;Lo;0;L;;;;;N;;;;;
+10461;SHAVIAN LETTER JUDGE;Lo;0;L;;;;;N;;;;;
+10462;SHAVIAN LETTER WOE;Lo;0;L;;;;;N;;;;;
+10463;SHAVIAN LETTER HA-HA;Lo;0;L;;;;;N;;;;;
+10464;SHAVIAN LETTER LOLL;Lo;0;L;;;;;N;;;;;
+10465;SHAVIAN LETTER MIME;Lo;0;L;;;;;N;;;;;
+10466;SHAVIAN LETTER IF;Lo;0;L;;;;;N;;;;;
+10467;SHAVIAN LETTER EGG;Lo;0;L;;;;;N;;;;;
+10468;SHAVIAN LETTER ASH;Lo;0;L;;;;;N;;;;;
+10469;SHAVIAN LETTER ADO;Lo;0;L;;;;;N;;;;;
+1046A;SHAVIAN LETTER ON;Lo;0;L;;;;;N;;;;;
+1046B;SHAVIAN LETTER WOOL;Lo;0;L;;;;;N;;;;;
+1046C;SHAVIAN LETTER OUT;Lo;0;L;;;;;N;;;;;
+1046D;SHAVIAN LETTER AH;Lo;0;L;;;;;N;;;;;
+1046E;SHAVIAN LETTER ROAR;Lo;0;L;;;;;N;;;;;
+1046F;SHAVIAN LETTER NUN;Lo;0;L;;;;;N;;;;;
+10470;SHAVIAN LETTER EAT;Lo;0;L;;;;;N;;;;;
+10471;SHAVIAN LETTER AGE;Lo;0;L;;;;;N;;;;;
+10472;SHAVIAN LETTER ICE;Lo;0;L;;;;;N;;;;;
+10473;SHAVIAN LETTER UP;Lo;0;L;;;;;N;;;;;
+10474;SHAVIAN LETTER OAK;Lo;0;L;;;;;N;;;;;
+10475;SHAVIAN LETTER OOZE;Lo;0;L;;;;;N;;;;;
+10476;SHAVIAN LETTER OIL;Lo;0;L;;;;;N;;;;;
+10477;SHAVIAN LETTER AWE;Lo;0;L;;;;;N;;;;;
+10478;SHAVIAN LETTER ARE;Lo;0;L;;;;;N;;;;;
+10479;SHAVIAN LETTER OR;Lo;0;L;;;;;N;;;;;
+1047A;SHAVIAN LETTER AIR;Lo;0;L;;;;;N;;;;;
+1047B;SHAVIAN LETTER ERR;Lo;0;L;;;;;N;;;;;
+1047C;SHAVIAN LETTER ARRAY;Lo;0;L;;;;;N;;;;;
+1047D;SHAVIAN LETTER EAR;Lo;0;L;;;;;N;;;;;
+1047E;SHAVIAN LETTER IAN;Lo;0;L;;;;;N;;;;;
+1047F;SHAVIAN LETTER YEW;Lo;0;L;;;;;N;;;;;
+10480;OSMANYA LETTER ALEF;Lo;0;L;;;;;N;;;;;
+10481;OSMANYA LETTER BA;Lo;0;L;;;;;N;;;;;
+10482;OSMANYA LETTER TA;Lo;0;L;;;;;N;;;;;
+10483;OSMANYA LETTER JA;Lo;0;L;;;;;N;;;;;
+10484;OSMANYA LETTER XA;Lo;0;L;;;;;N;;;;;
+10485;OSMANYA LETTER KHA;Lo;0;L;;;;;N;;;;;
+10486;OSMANYA LETTER DEEL;Lo;0;L;;;;;N;;;;;
+10487;OSMANYA LETTER RA;Lo;0;L;;;;;N;;;;;
+10488;OSMANYA LETTER SA;Lo;0;L;;;;;N;;;;;
+10489;OSMANYA LETTER SHIIN;Lo;0;L;;;;;N;;;;;
+1048A;OSMANYA LETTER DHA;Lo;0;L;;;;;N;;;;;
+1048B;OSMANYA LETTER CAYN;Lo;0;L;;;;;N;;;;;
+1048C;OSMANYA LETTER GA;Lo;0;L;;;;;N;;;;;
+1048D;OSMANYA LETTER FA;Lo;0;L;;;;;N;;;;;
+1048E;OSMANYA LETTER QAAF;Lo;0;L;;;;;N;;;;;
+1048F;OSMANYA LETTER KAAF;Lo;0;L;;;;;N;;;;;
+10490;OSMANYA LETTER LAAN;Lo;0;L;;;;;N;;;;;
+10491;OSMANYA LETTER MIIN;Lo;0;L;;;;;N;;;;;
+10492;OSMANYA LETTER NUUN;Lo;0;L;;;;;N;;;;;
+10493;OSMANYA LETTER WAW;Lo;0;L;;;;;N;;;;;
+10494;OSMANYA LETTER HA;Lo;0;L;;;;;N;;;;;
+10495;OSMANYA LETTER YA;Lo;0;L;;;;;N;;;;;
+10496;OSMANYA LETTER A;Lo;0;L;;;;;N;;;;;
+10497;OSMANYA LETTER E;Lo;0;L;;;;;N;;;;;
+10498;OSMANYA LETTER I;Lo;0;L;;;;;N;;;;;
+10499;OSMANYA LETTER O;Lo;0;L;;;;;N;;;;;
+1049A;OSMANYA LETTER U;Lo;0;L;;;;;N;;;;;
+1049B;OSMANYA LETTER AA;Lo;0;L;;;;;N;;;;;
+1049C;OSMANYA LETTER EE;Lo;0;L;;;;;N;;;;;
+1049D;OSMANYA LETTER OO;Lo;0;L;;;;;N;;;;;
+104A0;OSMANYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+104A1;OSMANYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+104A2;OSMANYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+104A3;OSMANYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+104A4;OSMANYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+104A5;OSMANYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+104A6;OSMANYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;;
+10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;;
+10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;;
+10803;CYPRIOT SYLLABLE O;Lo;0;R;;;;;N;;;;;
+10804;CYPRIOT SYLLABLE U;Lo;0;R;;;;;N;;;;;
+10805;CYPRIOT SYLLABLE JA;Lo;0;R;;;;;N;;;;;
+10808;CYPRIOT SYLLABLE JO;Lo;0;R;;;;;N;;;;;
+1080A;CYPRIOT SYLLABLE KA;Lo;0;R;;;;;N;;;;;
+1080B;CYPRIOT SYLLABLE KE;Lo;0;R;;;;;N;;;;;
+1080C;CYPRIOT SYLLABLE KI;Lo;0;R;;;;;N;;;;;
+1080D;CYPRIOT SYLLABLE KO;Lo;0;R;;;;;N;;;;;
+1080E;CYPRIOT SYLLABLE KU;Lo;0;R;;;;;N;;;;;
+1080F;CYPRIOT SYLLABLE LA;Lo;0;R;;;;;N;;;;;
+10810;CYPRIOT SYLLABLE LE;Lo;0;R;;;;;N;;;;;
+10811;CYPRIOT SYLLABLE LI;Lo;0;R;;;;;N;;;;;
+10812;CYPRIOT SYLLABLE LO;Lo;0;R;;;;;N;;;;;
+10813;CYPRIOT SYLLABLE LU;Lo;0;R;;;;;N;;;;;
+10814;CYPRIOT SYLLABLE MA;Lo;0;R;;;;;N;;;;;
+10815;CYPRIOT SYLLABLE ME;Lo;0;R;;;;;N;;;;;
+10816;CYPRIOT SYLLABLE MI;Lo;0;R;;;;;N;;;;;
+10817;CYPRIOT SYLLABLE MO;Lo;0;R;;;;;N;;;;;
+10818;CYPRIOT SYLLABLE MU;Lo;0;R;;;;;N;;;;;
+10819;CYPRIOT SYLLABLE NA;Lo;0;R;;;;;N;;;;;
+1081A;CYPRIOT SYLLABLE NE;Lo;0;R;;;;;N;;;;;
+1081B;CYPRIOT SYLLABLE NI;Lo;0;R;;;;;N;;;;;
+1081C;CYPRIOT SYLLABLE NO;Lo;0;R;;;;;N;;;;;
+1081D;CYPRIOT SYLLABLE NU;Lo;0;R;;;;;N;;;;;
+1081E;CYPRIOT SYLLABLE PA;Lo;0;R;;;;;N;;;;;
+1081F;CYPRIOT SYLLABLE PE;Lo;0;R;;;;;N;;;;;
+10820;CYPRIOT SYLLABLE PI;Lo;0;R;;;;;N;;;;;
+10821;CYPRIOT SYLLABLE PO;Lo;0;R;;;;;N;;;;;
+10822;CYPRIOT SYLLABLE PU;Lo;0;R;;;;;N;;;;;
+10823;CYPRIOT SYLLABLE RA;Lo;0;R;;;;;N;;;;;
+10824;CYPRIOT SYLLABLE RE;Lo;0;R;;;;;N;;;;;
+10825;CYPRIOT SYLLABLE RI;Lo;0;R;;;;;N;;;;;
+10826;CYPRIOT SYLLABLE RO;Lo;0;R;;;;;N;;;;;
+10827;CYPRIOT SYLLABLE RU;Lo;0;R;;;;;N;;;;;
+10828;CYPRIOT SYLLABLE SA;Lo;0;R;;;;;N;;;;;
+10829;CYPRIOT SYLLABLE SE;Lo;0;R;;;;;N;;;;;
+1082A;CYPRIOT SYLLABLE SI;Lo;0;R;;;;;N;;;;;
+1082B;CYPRIOT SYLLABLE SO;Lo;0;R;;;;;N;;;;;
+1082C;CYPRIOT SYLLABLE SU;Lo;0;R;;;;;N;;;;;
+1082D;CYPRIOT SYLLABLE TA;Lo;0;R;;;;;N;;;;;
+1082E;CYPRIOT SYLLABLE TE;Lo;0;R;;;;;N;;;;;
+1082F;CYPRIOT SYLLABLE TI;Lo;0;R;;;;;N;;;;;
+10830;CYPRIOT SYLLABLE TO;Lo;0;R;;;;;N;;;;;
+10831;CYPRIOT SYLLABLE TU;Lo;0;R;;;;;N;;;;;
+10832;CYPRIOT SYLLABLE WA;Lo;0;R;;;;;N;;;;;
+10833;CYPRIOT SYLLABLE WE;Lo;0;R;;;;;N;;;;;
+10834;CYPRIOT SYLLABLE WI;Lo;0;R;;;;;N;;;;;
+10835;CYPRIOT SYLLABLE WO;Lo;0;R;;;;;N;;;;;
+10837;CYPRIOT SYLLABLE XA;Lo;0;R;;;;;N;;;;;
+10838;CYPRIOT SYLLABLE XE;Lo;0;R;;;;;N;;;;;
+1083C;CYPRIOT SYLLABLE ZA;Lo;0;R;;;;;N;;;;;
+1083F;CYPRIOT SYLLABLE ZO;Lo;0;R;;;;;N;;;;;
+10840;IMPERIAL ARAMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;;
+10841;IMPERIAL ARAMAIC LETTER BETH;Lo;0;R;;;;;N;;;;;
+10842;IMPERIAL ARAMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;;
+10843;IMPERIAL ARAMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;;
+10844;IMPERIAL ARAMAIC LETTER HE;Lo;0;R;;;;;N;;;;;
+10845;IMPERIAL ARAMAIC LETTER WAW;Lo;0;R;;;;;N;;;;;
+10846;IMPERIAL ARAMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
+10847;IMPERIAL ARAMAIC LETTER HETH;Lo;0;R;;;;;N;;;;;
+10848;IMPERIAL ARAMAIC LETTER TETH;Lo;0;R;;;;;N;;;;;
+10849;IMPERIAL ARAMAIC LETTER YODH;Lo;0;R;;;;;N;;;;;
+1084A;IMPERIAL ARAMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;;
+1084B;IMPERIAL ARAMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
+1084C;IMPERIAL ARAMAIC LETTER MEM;Lo;0;R;;;;;N;;;;;
+1084D;IMPERIAL ARAMAIC LETTER NUN;Lo;0;R;;;;;N;;;;;
+1084E;IMPERIAL ARAMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
+1084F;IMPERIAL ARAMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;;
+10850;IMPERIAL ARAMAIC LETTER PE;Lo;0;R;;;;;N;;;;;
+10851;IMPERIAL ARAMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;;
+10852;IMPERIAL ARAMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;;
+10853;IMPERIAL ARAMAIC LETTER RESH;Lo;0;R;;;;;N;;;;;
+10854;IMPERIAL ARAMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;;
+10855;IMPERIAL ARAMAIC LETTER TAW;Lo;0;R;;;;;N;;;;;
+10857;IMPERIAL ARAMAIC SECTION SIGN;Po;0;R;;;;;N;;;;;
+10858;IMPERIAL ARAMAIC NUMBER ONE;No;0;R;;;;1;N;;;;;
+10859;IMPERIAL ARAMAIC NUMBER TWO;No;0;R;;;;2;N;;;;;
+1085A;IMPERIAL ARAMAIC NUMBER THREE;No;0;R;;;;3;N;;;;;
+1085B;IMPERIAL ARAMAIC NUMBER TEN;No;0;R;;;;10;N;;;;;
+1085C;IMPERIAL ARAMAIC NUMBER TWENTY;No;0;R;;;;20;N;;;;;
+1085D;IMPERIAL ARAMAIC NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+1085E;IMPERIAL ARAMAIC NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
+1085F;IMPERIAL ARAMAIC NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;;
+10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;;
+10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;;
+10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;;
+10903;PHOENICIAN LETTER DELT;Lo;0;R;;;;;N;;;;;
+10904;PHOENICIAN LETTER HE;Lo;0;R;;;;;N;;;;;
+10905;PHOENICIAN LETTER WAU;Lo;0;R;;;;;N;;;;;
+10906;PHOENICIAN LETTER ZAI;Lo;0;R;;;;;N;;;;;
+10907;PHOENICIAN LETTER HET;Lo;0;R;;;;;N;;;;;
+10908;PHOENICIAN LETTER TET;Lo;0;R;;;;;N;;;;;
+10909;PHOENICIAN LETTER YOD;Lo;0;R;;;;;N;;;;;
+1090A;PHOENICIAN LETTER KAF;Lo;0;R;;;;;N;;;;;
+1090B;PHOENICIAN LETTER LAMD;Lo;0;R;;;;;N;;;;;
+1090C;PHOENICIAN LETTER MEM;Lo;0;R;;;;;N;;;;;
+1090D;PHOENICIAN LETTER NUN;Lo;0;R;;;;;N;;;;;
+1090E;PHOENICIAN LETTER SEMK;Lo;0;R;;;;;N;;;;;
+1090F;PHOENICIAN LETTER AIN;Lo;0;R;;;;;N;;;;;
+10910;PHOENICIAN LETTER PE;Lo;0;R;;;;;N;;;;;
+10911;PHOENICIAN LETTER SADE;Lo;0;R;;;;;N;;;;;
+10912;PHOENICIAN LETTER QOF;Lo;0;R;;;;;N;;;;;
+10913;PHOENICIAN LETTER ROSH;Lo;0;R;;;;;N;;;;;
+10914;PHOENICIAN LETTER SHIN;Lo;0;R;;;;;N;;;;;
+10915;PHOENICIAN LETTER TAU;Lo;0;R;;;;;N;;;;;
+10916;PHOENICIAN NUMBER ONE;No;0;R;;;;1;N;;;;;
+10917;PHOENICIAN NUMBER TEN;No;0;R;;;;10;N;;;;;
+10918;PHOENICIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;;
+10919;PHOENICIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+1091A;PHOENICIAN NUMBER TWO;No;0;R;;;;2;N;;;;;
+1091B;PHOENICIAN NUMBER THREE;No;0;R;;;;3;N;;;;;
+1091F;PHOENICIAN WORD SEPARATOR;Po;0;ON;;;;;N;;;;;
+10920;LYDIAN LETTER A;Lo;0;R;;;;;N;;;;;
+10921;LYDIAN LETTER B;Lo;0;R;;;;;N;;;;;
+10922;LYDIAN LETTER G;Lo;0;R;;;;;N;;;;;
+10923;LYDIAN LETTER D;Lo;0;R;;;;;N;;;;;
+10924;LYDIAN LETTER E;Lo;0;R;;;;;N;;;;;
+10925;LYDIAN LETTER V;Lo;0;R;;;;;N;;;;;
+10926;LYDIAN LETTER I;Lo;0;R;;;;;N;;;;;
+10927;LYDIAN LETTER Y;Lo;0;R;;;;;N;;;;;
+10928;LYDIAN LETTER K;Lo;0;R;;;;;N;;;;;
+10929;LYDIAN LETTER L;Lo;0;R;;;;;N;;;;;
+1092A;LYDIAN LETTER M;Lo;0;R;;;;;N;;;;;
+1092B;LYDIAN LETTER N;Lo;0;R;;;;;N;;;;;
+1092C;LYDIAN LETTER O;Lo;0;R;;;;;N;;;;;
+1092D;LYDIAN LETTER R;Lo;0;R;;;;;N;;;;;
+1092E;LYDIAN LETTER SS;Lo;0;R;;;;;N;;;;;
+1092F;LYDIAN LETTER T;Lo;0;R;;;;;N;;;;;
+10930;LYDIAN LETTER U;Lo;0;R;;;;;N;;;;;
+10931;LYDIAN LETTER F;Lo;0;R;;;;;N;;;;;
+10932;LYDIAN LETTER Q;Lo;0;R;;;;;N;;;;;
+10933;LYDIAN LETTER S;Lo;0;R;;;;;N;;;;;
+10934;LYDIAN LETTER TT;Lo;0;R;;;;;N;;;;;
+10935;LYDIAN LETTER AN;Lo;0;R;;;;;N;;;;;
+10936;LYDIAN LETTER EN;Lo;0;R;;;;;N;;;;;
+10937;LYDIAN LETTER LY;Lo;0;R;;;;;N;;;;;
+10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;;
+10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;;
+1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;;
+10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;;
+10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+10A03;KHAROSHTHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+10A05;KHAROSHTHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+10A06;KHAROSHTHI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+10A0C;KHAROSHTHI VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;;
+10A0D;KHAROSHTHI SIGN DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;;
+10A0E;KHAROSHTHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+10A0F;KHAROSHTHI SIGN VISARGA;Mn;230;NSM;;;;;N;;;;;
+10A10;KHAROSHTHI LETTER KA;Lo;0;R;;;;;N;;;;;
+10A11;KHAROSHTHI LETTER KHA;Lo;0;R;;;;;N;;;;;
+10A12;KHAROSHTHI LETTER GA;Lo;0;R;;;;;N;;;;;
+10A13;KHAROSHTHI LETTER GHA;Lo;0;R;;;;;N;;;;;
+10A15;KHAROSHTHI LETTER CA;Lo;0;R;;;;;N;;;;;
+10A16;KHAROSHTHI LETTER CHA;Lo;0;R;;;;;N;;;;;
+10A17;KHAROSHTHI LETTER JA;Lo;0;R;;;;;N;;;;;
+10A19;KHAROSHTHI LETTER NYA;Lo;0;R;;;;;N;;;;;
+10A1A;KHAROSHTHI LETTER TTA;Lo;0;R;;;;;N;;;;;
+10A1B;KHAROSHTHI LETTER TTHA;Lo;0;R;;;;;N;;;;;
+10A1C;KHAROSHTHI LETTER DDA;Lo;0;R;;;;;N;;;;;
+10A1D;KHAROSHTHI LETTER DDHA;Lo;0;R;;;;;N;;;;;
+10A1E;KHAROSHTHI LETTER NNA;Lo;0;R;;;;;N;;;;;
+10A1F;KHAROSHTHI LETTER TA;Lo;0;R;;;;;N;;;;;
+10A20;KHAROSHTHI LETTER THA;Lo;0;R;;;;;N;;;;;
+10A21;KHAROSHTHI LETTER DA;Lo;0;R;;;;;N;;;;;
+10A22;KHAROSHTHI LETTER DHA;Lo;0;R;;;;;N;;;;;
+10A23;KHAROSHTHI LETTER NA;Lo;0;R;;;;;N;;;;;
+10A24;KHAROSHTHI LETTER PA;Lo;0;R;;;;;N;;;;;
+10A25;KHAROSHTHI LETTER PHA;Lo;0;R;;;;;N;;;;;
+10A26;KHAROSHTHI LETTER BA;Lo;0;R;;;;;N;;;;;
+10A27;KHAROSHTHI LETTER BHA;Lo;0;R;;;;;N;;;;;
+10A28;KHAROSHTHI LETTER MA;Lo;0;R;;;;;N;;;;;
+10A29;KHAROSHTHI LETTER YA;Lo;0;R;;;;;N;;;;;
+10A2A;KHAROSHTHI LETTER RA;Lo;0;R;;;;;N;;;;;
+10A2B;KHAROSHTHI LETTER LA;Lo;0;R;;;;;N;;;;;
+10A2C;KHAROSHTHI LETTER VA;Lo;0;R;;;;;N;;;;;
+10A2D;KHAROSHTHI LETTER SHA;Lo;0;R;;;;;N;;;;;
+10A2E;KHAROSHTHI LETTER SSA;Lo;0;R;;;;;N;;;;;
+10A2F;KHAROSHTHI LETTER SA;Lo;0;R;;;;;N;;;;;
+10A30;KHAROSHTHI LETTER ZA;Lo;0;R;;;;;N;;;;;
+10A31;KHAROSHTHI LETTER HA;Lo;0;R;;;;;N;;;;;
+10A32;KHAROSHTHI LETTER KKA;Lo;0;R;;;;;N;;;;;
+10A33;KHAROSHTHI LETTER TTTHA;Lo;0;R;;;;;N;;;;;
+10A38;KHAROSHTHI SIGN BAR ABOVE;Mn;230;NSM;;;;;N;;;;;
+10A39;KHAROSHTHI SIGN CAUDA;Mn;1;NSM;;;;;N;;;;;
+10A3A;KHAROSHTHI SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;;
+10A3F;KHAROSHTHI VIRAMA;Mn;9;NSM;;;;;N;;;;;
+10A40;KHAROSHTHI DIGIT ONE;No;0;R;;;1;1;N;;;;;
+10A41;KHAROSHTHI DIGIT TWO;No;0;R;;;2;2;N;;;;;
+10A42;KHAROSHTHI DIGIT THREE;No;0;R;;;3;3;N;;;;;
+10A43;KHAROSHTHI DIGIT FOUR;No;0;R;;;4;4;N;;;;;
+10A44;KHAROSHTHI NUMBER TEN;No;0;R;;;;10;N;;;;;
+10A45;KHAROSHTHI NUMBER TWENTY;No;0;R;;;;20;N;;;;;
+10A46;KHAROSHTHI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+10A47;KHAROSHTHI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
+10A50;KHAROSHTHI PUNCTUATION DOT;Po;0;R;;;;;N;;;;;
+10A51;KHAROSHTHI PUNCTUATION SMALL CIRCLE;Po;0;R;;;;;N;;;;;
+10A52;KHAROSHTHI PUNCTUATION CIRCLE;Po;0;R;;;;;N;;;;;
+10A53;KHAROSHTHI PUNCTUATION CRESCENT BAR;Po;0;R;;;;;N;;;;;
+10A54;KHAROSHTHI PUNCTUATION MANGALAM;Po;0;R;;;;;N;;;;;
+10A55;KHAROSHTHI PUNCTUATION LOTUS;Po;0;R;;;;;N;;;;;
+10A56;KHAROSHTHI PUNCTUATION DANDA;Po;0;R;;;;;N;;;;;
+10A57;KHAROSHTHI PUNCTUATION DOUBLE DANDA;Po;0;R;;;;;N;;;;;
+10A58;KHAROSHTHI PUNCTUATION LINES;Po;0;R;;;;;N;;;;;
+10A60;OLD SOUTH ARABIAN LETTER HE;Lo;0;R;;;;;N;;;;;
+10A61;OLD SOUTH ARABIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
+10A62;OLD SOUTH ARABIAN LETTER HETH;Lo;0;R;;;;;N;;;;;
+10A63;OLD SOUTH ARABIAN LETTER MEM;Lo;0;R;;;;;N;;;;;
+10A64;OLD SOUTH ARABIAN LETTER QOPH;Lo;0;R;;;;;N;;;;;
+10A65;OLD SOUTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;;
+10A66;OLD SOUTH ARABIAN LETTER SHIN;Lo;0;R;;;;;N;;;;;
+10A67;OLD SOUTH ARABIAN LETTER RESH;Lo;0;R;;;;;N;;;;;
+10A68;OLD SOUTH ARABIAN LETTER BETH;Lo;0;R;;;;;N;;;;;
+10A69;OLD SOUTH ARABIAN LETTER TAW;Lo;0;R;;;;;N;;;;;
+10A6A;OLD SOUTH ARABIAN LETTER SAT;Lo;0;R;;;;;N;;;;;
+10A6B;OLD SOUTH ARABIAN LETTER KAPH;Lo;0;R;;;;;N;;;;;
+10A6C;OLD SOUTH ARABIAN LETTER NUN;Lo;0;R;;;;;N;;;;;
+10A6D;OLD SOUTH ARABIAN LETTER KHETH;Lo;0;R;;;;;N;;;;;
+10A6E;OLD SOUTH ARABIAN LETTER SADHE;Lo;0;R;;;;;N;;;;;
+10A6F;OLD SOUTH ARABIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
+10A70;OLD SOUTH ARABIAN LETTER FE;Lo;0;R;;;;;N;;;;;
+10A71;OLD SOUTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;;
+10A72;OLD SOUTH ARABIAN LETTER AYN;Lo;0;R;;;;;N;;;;;
+10A73;OLD SOUTH ARABIAN LETTER DHADHE;Lo;0;R;;;;;N;;;;;
+10A74;OLD SOUTH ARABIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;;
+10A75;OLD SOUTH ARABIAN LETTER DALETH;Lo;0;R;;;;;N;;;;;
+10A76;OLD SOUTH ARABIAN LETTER GHAYN;Lo;0;R;;;;;N;;;;;
+10A77;OLD SOUTH ARABIAN LETTER TETH;Lo;0;R;;;;;N;;;;;
+10A78;OLD SOUTH ARABIAN LETTER ZAYN;Lo;0;R;;;;;N;;;;;
+10A79;OLD SOUTH ARABIAN LETTER DHALETH;Lo;0;R;;;;;N;;;;;
+10A7A;OLD SOUTH ARABIAN LETTER YODH;Lo;0;R;;;;;N;;;;;
+10A7B;OLD SOUTH ARABIAN LETTER THAW;Lo;0;R;;;;;N;;;;;
+10A7C;OLD SOUTH ARABIAN LETTER THETH;Lo;0;R;;;;;N;;;;;
+10A7D;OLD SOUTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;;
+10A7E;OLD SOUTH ARABIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;;
+10A7F;OLD SOUTH ARABIAN NUMERIC INDICATOR;Po;0;R;;;;;N;;;;;
+10B00;AVESTAN LETTER A;Lo;0;R;;;;;N;;;;;
+10B01;AVESTAN LETTER AA;Lo;0;R;;;;;N;;;;;
+10B02;AVESTAN LETTER AO;Lo;0;R;;;;;N;;;;;
+10B03;AVESTAN LETTER AAO;Lo;0;R;;;;;N;;;;;
+10B04;AVESTAN LETTER AN;Lo;0;R;;;;;N;;;;;
+10B05;AVESTAN LETTER AAN;Lo;0;R;;;;;N;;;;;
+10B06;AVESTAN LETTER AE;Lo;0;R;;;;;N;;;;;
+10B07;AVESTAN LETTER AEE;Lo;0;R;;;;;N;;;;;
+10B08;AVESTAN LETTER E;Lo;0;R;;;;;N;;;;;
+10B09;AVESTAN LETTER EE;Lo;0;R;;;;;N;;;;;
+10B0A;AVESTAN LETTER O;Lo;0;R;;;;;N;;;;;
+10B0B;AVESTAN LETTER OO;Lo;0;R;;;;;N;;;;;
+10B0C;AVESTAN LETTER I;Lo;0;R;;;;;N;;;;;
+10B0D;AVESTAN LETTER II;Lo;0;R;;;;;N;;;;;
+10B0E;AVESTAN LETTER U;Lo;0;R;;;;;N;;;;;
+10B0F;AVESTAN LETTER UU;Lo;0;R;;;;;N;;;;;
+10B10;AVESTAN LETTER KE;Lo;0;R;;;;;N;;;;;
+10B11;AVESTAN LETTER XE;Lo;0;R;;;;;N;;;;;
+10B12;AVESTAN LETTER XYE;Lo;0;R;;;;;N;;;;;
+10B13;AVESTAN LETTER XVE;Lo;0;R;;;;;N;;;;;
+10B14;AVESTAN LETTER GE;Lo;0;R;;;;;N;;;;;
+10B15;AVESTAN LETTER GGE;Lo;0;R;;;;;N;;;;;
+10B16;AVESTAN LETTER GHE;Lo;0;R;;;;;N;;;;;
+10B17;AVESTAN LETTER CE;Lo;0;R;;;;;N;;;;;
+10B18;AVESTAN LETTER JE;Lo;0;R;;;;;N;;;;;
+10B19;AVESTAN LETTER TE;Lo;0;R;;;;;N;;;;;
+10B1A;AVESTAN LETTER THE;Lo;0;R;;;;;N;;;;;
+10B1B;AVESTAN LETTER DE;Lo;0;R;;;;;N;;;;;
+10B1C;AVESTAN LETTER DHE;Lo;0;R;;;;;N;;;;;
+10B1D;AVESTAN LETTER TTE;Lo;0;R;;;;;N;;;;;
+10B1E;AVESTAN LETTER PE;Lo;0;R;;;;;N;;;;;
+10B1F;AVESTAN LETTER FE;Lo;0;R;;;;;N;;;;;
+10B20;AVESTAN LETTER BE;Lo;0;R;;;;;N;;;;;
+10B21;AVESTAN LETTER BHE;Lo;0;R;;;;;N;;;;;
+10B22;AVESTAN LETTER NGE;Lo;0;R;;;;;N;;;;;
+10B23;AVESTAN LETTER NGYE;Lo;0;R;;;;;N;;;;;
+10B24;AVESTAN LETTER NGVE;Lo;0;R;;;;;N;;;;;
+10B25;AVESTAN LETTER NE;Lo;0;R;;;;;N;;;;;
+10B26;AVESTAN LETTER NYE;Lo;0;R;;;;;N;;;;;
+10B27;AVESTAN LETTER NNE;Lo;0;R;;;;;N;;;;;
+10B28;AVESTAN LETTER ME;Lo;0;R;;;;;N;;;;;
+10B29;AVESTAN LETTER HME;Lo;0;R;;;;;N;;;;;
+10B2A;AVESTAN LETTER YYE;Lo;0;R;;;;;N;;;;;
+10B2B;AVESTAN LETTER YE;Lo;0;R;;;;;N;;;;;
+10B2C;AVESTAN LETTER VE;Lo;0;R;;;;;N;;;;;
+10B2D;AVESTAN LETTER RE;Lo;0;R;;;;;N;;;;;
+10B2E;AVESTAN LETTER LE;Lo;0;R;;;;;N;;;;;
+10B2F;AVESTAN LETTER SE;Lo;0;R;;;;;N;;;;;
+10B30;AVESTAN LETTER ZE;Lo;0;R;;;;;N;;;;;
+10B31;AVESTAN LETTER SHE;Lo;0;R;;;;;N;;;;;
+10B32;AVESTAN LETTER ZHE;Lo;0;R;;;;;N;;;;;
+10B33;AVESTAN LETTER SHYE;Lo;0;R;;;;;N;;;;;
+10B34;AVESTAN LETTER SSHE;Lo;0;R;;;;;N;;;;;
+10B35;AVESTAN LETTER HE;Lo;0;R;;;;;N;;;;;
+10B39;AVESTAN ABBREVIATION MARK;Po;0;ON;;;;;N;;;;;
+10B3A;TINY TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+10B3B;SMALL TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+10B3C;LARGE TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;;
+10B3D;LARGE ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;;
+10B3E;LARGE TWO RINGS OVER ONE RING PUNCTUATION;Po;0;ON;;;;;N;;;;;
+10B3F;LARGE ONE RING OVER TWO RINGS PUNCTUATION;Po;0;ON;;;;;N;;;;;
+10B40;INSCRIPTIONAL PARTHIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;;
+10B41;INSCRIPTIONAL PARTHIAN LETTER BETH;Lo;0;R;;;;;N;;;;;
+10B42;INSCRIPTIONAL PARTHIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;;
+10B43;INSCRIPTIONAL PARTHIAN LETTER DALETH;Lo;0;R;;;;;N;;;;;
+10B44;INSCRIPTIONAL PARTHIAN LETTER HE;Lo;0;R;;;;;N;;;;;
+10B45;INSCRIPTIONAL PARTHIAN LETTER WAW;Lo;0;R;;;;;N;;;;;
+10B46;INSCRIPTIONAL PARTHIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
+10B47;INSCRIPTIONAL PARTHIAN LETTER HETH;Lo;0;R;;;;;N;;;;;
+10B48;INSCRIPTIONAL PARTHIAN LETTER TETH;Lo;0;R;;;;;N;;;;;
+10B49;INSCRIPTIONAL PARTHIAN LETTER YODH;Lo;0;R;;;;;N;;;;;
+10B4A;INSCRIPTIONAL PARTHIAN LETTER KAPH;Lo;0;R;;;;;N;;;;;
+10B4B;INSCRIPTIONAL PARTHIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
+10B4C;INSCRIPTIONAL PARTHIAN LETTER MEM;Lo;0;R;;;;;N;;;;;
+10B4D;INSCRIPTIONAL PARTHIAN LETTER NUN;Lo;0;R;;;;;N;;;;;
+10B4E;INSCRIPTIONAL PARTHIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
+10B4F;INSCRIPTIONAL PARTHIAN LETTER AYIN;Lo;0;R;;;;;N;;;;;
+10B50;INSCRIPTIONAL PARTHIAN LETTER PE;Lo;0;R;;;;;N;;;;;
+10B51;INSCRIPTIONAL PARTHIAN LETTER SADHE;Lo;0;R;;;;;N;;;;;
+10B52;INSCRIPTIONAL PARTHIAN LETTER QOPH;Lo;0;R;;;;;N;;;;;
+10B53;INSCRIPTIONAL PARTHIAN LETTER RESH;Lo;0;R;;;;;N;;;;;
+10B54;INSCRIPTIONAL PARTHIAN LETTER SHIN;Lo;0;R;;;;;N;;;;;
+10B55;INSCRIPTIONAL PARTHIAN LETTER TAW;Lo;0;R;;;;;N;;;;;
+10B58;INSCRIPTIONAL PARTHIAN NUMBER ONE;No;0;R;;;;1;N;;;;;
+10B59;INSCRIPTIONAL PARTHIAN NUMBER TWO;No;0;R;;;;2;N;;;;;
+10B5A;INSCRIPTIONAL PARTHIAN NUMBER THREE;No;0;R;;;;3;N;;;;;
+10B5B;INSCRIPTIONAL PARTHIAN NUMBER FOUR;No;0;R;;;;4;N;;;;;
+10B5C;INSCRIPTIONAL PARTHIAN NUMBER TEN;No;0;R;;;;10;N;;;;;
+10B5D;INSCRIPTIONAL PARTHIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;;
+10B5E;INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+10B5F;INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
+10B60;INSCRIPTIONAL PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;;
+10B61;INSCRIPTIONAL PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;;
+10B62;INSCRIPTIONAL PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;;
+10B63;INSCRIPTIONAL PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;;
+10B64;INSCRIPTIONAL PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;;
+10B65;INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;;
+10B66;INSCRIPTIONAL PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
+10B67;INSCRIPTIONAL PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;;
+10B68;INSCRIPTIONAL PAHLAVI LETTER TETH;Lo;0;R;;;;;N;;;;;
+10B69;INSCRIPTIONAL PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;;
+10B6A;INSCRIPTIONAL PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;;
+10B6B;INSCRIPTIONAL PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
+10B6C;INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;;
+10B6D;INSCRIPTIONAL PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;;
+10B6E;INSCRIPTIONAL PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
+10B6F;INSCRIPTIONAL PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;;
+10B70;INSCRIPTIONAL PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;;
+10B71;INSCRIPTIONAL PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;;
+10B72;INSCRIPTIONAL PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;;
+10B78;INSCRIPTIONAL PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;;
+10B79;INSCRIPTIONAL PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;;
+10B7A;INSCRIPTIONAL PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;;
+10B7B;INSCRIPTIONAL PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;;
+10B7C;INSCRIPTIONAL PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;;
+10B7D;INSCRIPTIONAL PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;;
+10B7E;INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+10B7F;INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
+10C00;OLD TURKIC LETTER ORKHON A;Lo;0;R;;;;;N;;;;;
+10C01;OLD TURKIC LETTER YENISEI A;Lo;0;R;;;;;N;;;;;
+10C02;OLD TURKIC LETTER YENISEI AE;Lo;0;R;;;;;N;;;;;
+10C03;OLD TURKIC LETTER ORKHON I;Lo;0;R;;;;;N;;;;;
+10C04;OLD TURKIC LETTER YENISEI I;Lo;0;R;;;;;N;;;;;
+10C05;OLD TURKIC LETTER YENISEI E;Lo;0;R;;;;;N;;;;;
+10C06;OLD TURKIC LETTER ORKHON O;Lo;0;R;;;;;N;;;;;
+10C07;OLD TURKIC LETTER ORKHON OE;Lo;0;R;;;;;N;;;;;
+10C08;OLD TURKIC LETTER YENISEI OE;Lo;0;R;;;;;N;;;;;
+10C09;OLD TURKIC LETTER ORKHON AB;Lo;0;R;;;;;N;;;;;
+10C0A;OLD TURKIC LETTER YENISEI AB;Lo;0;R;;;;;N;;;;;
+10C0B;OLD TURKIC LETTER ORKHON AEB;Lo;0;R;;;;;N;;;;;
+10C0C;OLD TURKIC LETTER YENISEI AEB;Lo;0;R;;;;;N;;;;;
+10C0D;OLD TURKIC LETTER ORKHON AG;Lo;0;R;;;;;N;;;;;
+10C0E;OLD TURKIC LETTER YENISEI AG;Lo;0;R;;;;;N;;;;;
+10C0F;OLD TURKIC LETTER ORKHON AEG;Lo;0;R;;;;;N;;;;;
+10C10;OLD TURKIC LETTER YENISEI AEG;Lo;0;R;;;;;N;;;;;
+10C11;OLD TURKIC LETTER ORKHON AD;Lo;0;R;;;;;N;;;;;
+10C12;OLD TURKIC LETTER YENISEI AD;Lo;0;R;;;;;N;;;;;
+10C13;OLD TURKIC LETTER ORKHON AED;Lo;0;R;;;;;N;;;;;
+10C14;OLD TURKIC LETTER ORKHON EZ;Lo;0;R;;;;;N;;;;;
+10C15;OLD TURKIC LETTER YENISEI EZ;Lo;0;R;;;;;N;;;;;
+10C16;OLD TURKIC LETTER ORKHON AY;Lo;0;R;;;;;N;;;;;
+10C17;OLD TURKIC LETTER YENISEI AY;Lo;0;R;;;;;N;;;;;
+10C18;OLD TURKIC LETTER ORKHON AEY;Lo;0;R;;;;;N;;;;;
+10C19;OLD TURKIC LETTER YENISEI AEY;Lo;0;R;;;;;N;;;;;
+10C1A;OLD TURKIC LETTER ORKHON AEK;Lo;0;R;;;;;N;;;;;
+10C1B;OLD TURKIC LETTER YENISEI AEK;Lo;0;R;;;;;N;;;;;
+10C1C;OLD TURKIC LETTER ORKHON OEK;Lo;0;R;;;;;N;;;;;
+10C1D;OLD TURKIC LETTER YENISEI OEK;Lo;0;R;;;;;N;;;;;
+10C1E;OLD TURKIC LETTER ORKHON AL;Lo;0;R;;;;;N;;;;;
+10C1F;OLD TURKIC LETTER YENISEI AL;Lo;0;R;;;;;N;;;;;
+10C20;OLD TURKIC LETTER ORKHON AEL;Lo;0;R;;;;;N;;;;;
+10C21;OLD TURKIC LETTER ORKHON ELT;Lo;0;R;;;;;N;;;;;
+10C22;OLD TURKIC LETTER ORKHON EM;Lo;0;R;;;;;N;;;;;
+10C23;OLD TURKIC LETTER ORKHON AN;Lo;0;R;;;;;N;;;;;
+10C24;OLD TURKIC LETTER ORKHON AEN;Lo;0;R;;;;;N;;;;;
+10C25;OLD TURKIC LETTER YENISEI AEN;Lo;0;R;;;;;N;;;;;
+10C26;OLD TURKIC LETTER ORKHON ENT;Lo;0;R;;;;;N;;;;;
+10C27;OLD TURKIC LETTER YENISEI ENT;Lo;0;R;;;;;N;;;;;
+10C28;OLD TURKIC LETTER ORKHON ENC;Lo;0;R;;;;;N;;;;;
+10C29;OLD TURKIC LETTER YENISEI ENC;Lo;0;R;;;;;N;;;;;
+10C2A;OLD TURKIC LETTER ORKHON ENY;Lo;0;R;;;;;N;;;;;
+10C2B;OLD TURKIC LETTER YENISEI ENY;Lo;0;R;;;;;N;;;;;
+10C2C;OLD TURKIC LETTER YENISEI ANG;Lo;0;R;;;;;N;;;;;
+10C2D;OLD TURKIC LETTER ORKHON ENG;Lo;0;R;;;;;N;;;;;
+10C2E;OLD TURKIC LETTER YENISEI AENG;Lo;0;R;;;;;N;;;;;
+10C2F;OLD TURKIC LETTER ORKHON EP;Lo;0;R;;;;;N;;;;;
+10C30;OLD TURKIC LETTER ORKHON OP;Lo;0;R;;;;;N;;;;;
+10C31;OLD TURKIC LETTER ORKHON IC;Lo;0;R;;;;;N;;;;;
+10C32;OLD TURKIC LETTER ORKHON EC;Lo;0;R;;;;;N;;;;;
+10C33;OLD TURKIC LETTER YENISEI EC;Lo;0;R;;;;;N;;;;;
+10C34;OLD TURKIC LETTER ORKHON AQ;Lo;0;R;;;;;N;;;;;
+10C35;OLD TURKIC LETTER YENISEI AQ;Lo;0;R;;;;;N;;;;;
+10C36;OLD TURKIC LETTER ORKHON IQ;Lo;0;R;;;;;N;;;;;
+10C37;OLD TURKIC LETTER YENISEI IQ;Lo;0;R;;;;;N;;;;;
+10C38;OLD TURKIC LETTER ORKHON OQ;Lo;0;R;;;;;N;;;;;
+10C39;OLD TURKIC LETTER YENISEI OQ;Lo;0;R;;;;;N;;;;;
+10C3A;OLD TURKIC LETTER ORKHON AR;Lo;0;R;;;;;N;;;;;
+10C3B;OLD TURKIC LETTER YENISEI AR;Lo;0;R;;;;;N;;;;;
+10C3C;OLD TURKIC LETTER ORKHON AER;Lo;0;R;;;;;N;;;;;
+10C3D;OLD TURKIC LETTER ORKHON AS;Lo;0;R;;;;;N;;;;;
+10C3E;OLD TURKIC LETTER ORKHON AES;Lo;0;R;;;;;N;;;;;
+10C3F;OLD TURKIC LETTER ORKHON ASH;Lo;0;R;;;;;N;;;;;
+10C40;OLD TURKIC LETTER YENISEI ASH;Lo;0;R;;;;;N;;;;;
+10C41;OLD TURKIC LETTER ORKHON ESH;Lo;0;R;;;;;N;;;;;
+10C42;OLD TURKIC LETTER YENISEI ESH;Lo;0;R;;;;;N;;;;;
+10C43;OLD TURKIC LETTER ORKHON AT;Lo;0;R;;;;;N;;;;;
+10C44;OLD TURKIC LETTER YENISEI AT;Lo;0;R;;;;;N;;;;;
+10C45;OLD TURKIC LETTER ORKHON AET;Lo;0;R;;;;;N;;;;;
+10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;;
+10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;;
+10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;;
+10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;;
+10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;;
+10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;;
+10E63;RUMI DIGIT FOUR;No;0;AN;;;4;4;N;;;;;
+10E64;RUMI DIGIT FIVE;No;0;AN;;;5;5;N;;;;;
+10E65;RUMI DIGIT SIX;No;0;AN;;;6;6;N;;;;;
+10E66;RUMI DIGIT SEVEN;No;0;AN;;;7;7;N;;;;;
+10E67;RUMI DIGIT EIGHT;No;0;AN;;;8;8;N;;;;;
+10E68;RUMI DIGIT NINE;No;0;AN;;;9;9;N;;;;;
+10E69;RUMI NUMBER TEN;No;0;AN;;;;10;N;;;;;
+10E6A;RUMI NUMBER TWENTY;No;0;AN;;;;20;N;;;;;
+10E6B;RUMI NUMBER THIRTY;No;0;AN;;;;30;N;;;;;
+10E6C;RUMI NUMBER FORTY;No;0;AN;;;;40;N;;;;;
+10E6D;RUMI NUMBER FIFTY;No;0;AN;;;;50;N;;;;;
+10E6E;RUMI NUMBER SIXTY;No;0;AN;;;;60;N;;;;;
+10E6F;RUMI NUMBER SEVENTY;No;0;AN;;;;70;N;;;;;
+10E70;RUMI NUMBER EIGHTY;No;0;AN;;;;80;N;;;;;
+10E71;RUMI NUMBER NINETY;No;0;AN;;;;90;N;;;;;
+10E72;RUMI NUMBER ONE HUNDRED;No;0;AN;;;;100;N;;;;;
+10E73;RUMI NUMBER TWO HUNDRED;No;0;AN;;;;200;N;;;;;
+10E74;RUMI NUMBER THREE HUNDRED;No;0;AN;;;;300;N;;;;;
+10E75;RUMI NUMBER FOUR HUNDRED;No;0;AN;;;;400;N;;;;;
+10E76;RUMI NUMBER FIVE HUNDRED;No;0;AN;;;;500;N;;;;;
+10E77;RUMI NUMBER SIX HUNDRED;No;0;AN;;;;600;N;;;;;
+10E78;RUMI NUMBER SEVEN HUNDRED;No;0;AN;;;;700;N;;;;;
+10E79;RUMI NUMBER EIGHT HUNDRED;No;0;AN;;;;800;N;;;;;
+10E7A;RUMI NUMBER NINE HUNDRED;No;0;AN;;;;900;N;;;;;
+10E7B;RUMI FRACTION ONE HALF;No;0;AN;;;;1/2;N;;;;;
+10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;;
+10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;;
+10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;;
+11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+11083;KAITHI LETTER A;Lo;0;L;;;;;N;;;;;
+11084;KAITHI LETTER AA;Lo;0;L;;;;;N;;;;;
+11085;KAITHI LETTER I;Lo;0;L;;;;;N;;;;;
+11086;KAITHI LETTER II;Lo;0;L;;;;;N;;;;;
+11087;KAITHI LETTER U;Lo;0;L;;;;;N;;;;;
+11088;KAITHI LETTER UU;Lo;0;L;;;;;N;;;;;
+11089;KAITHI LETTER E;Lo;0;L;;;;;N;;;;;
+1108A;KAITHI LETTER AI;Lo;0;L;;;;;N;;;;;
+1108B;KAITHI LETTER O;Lo;0;L;;;;;N;;;;;
+1108C;KAITHI LETTER AU;Lo;0;L;;;;;N;;;;;
+1108D;KAITHI LETTER KA;Lo;0;L;;;;;N;;;;;
+1108E;KAITHI LETTER KHA;Lo;0;L;;;;;N;;;;;
+1108F;KAITHI LETTER GA;Lo;0;L;;;;;N;;;;;
+11090;KAITHI LETTER GHA;Lo;0;L;;;;;N;;;;;
+11091;KAITHI LETTER NGA;Lo;0;L;;;;;N;;;;;
+11092;KAITHI LETTER CA;Lo;0;L;;;;;N;;;;;
+11093;KAITHI LETTER CHA;Lo;0;L;;;;;N;;;;;
+11094;KAITHI LETTER JA;Lo;0;L;;;;;N;;;;;
+11095;KAITHI LETTER JHA;Lo;0;L;;;;;N;;;;;
+11096;KAITHI LETTER NYA;Lo;0;L;;;;;N;;;;;
+11097;KAITHI LETTER TTA;Lo;0;L;;;;;N;;;;;
+11098;KAITHI LETTER TTHA;Lo;0;L;;;;;N;;;;;
+11099;KAITHI LETTER DDA;Lo;0;L;;;;;N;;;;;
+1109A;KAITHI LETTER DDDHA;Lo;0;L;11099 110BA;;;;N;;;;;
+1109B;KAITHI LETTER DDHA;Lo;0;L;;;;;N;;;;;
+1109C;KAITHI LETTER RHA;Lo;0;L;1109B 110BA;;;;N;;;;;
+1109D;KAITHI LETTER NNA;Lo;0;L;;;;;N;;;;;
+1109E;KAITHI LETTER TA;Lo;0;L;;;;;N;;;;;
+1109F;KAITHI LETTER THA;Lo;0;L;;;;;N;;;;;
+110A0;KAITHI LETTER DA;Lo;0;L;;;;;N;;;;;
+110A1;KAITHI LETTER DHA;Lo;0;L;;;;;N;;;;;
+110A2;KAITHI LETTER NA;Lo;0;L;;;;;N;;;;;
+110A3;KAITHI LETTER PA;Lo;0;L;;;;;N;;;;;
+110A4;KAITHI LETTER PHA;Lo;0;L;;;;;N;;;;;
+110A5;KAITHI LETTER BA;Lo;0;L;;;;;N;;;;;
+110A6;KAITHI LETTER BHA;Lo;0;L;;;;;N;;;;;
+110A7;KAITHI LETTER MA;Lo;0;L;;;;;N;;;;;
+110A8;KAITHI LETTER YA;Lo;0;L;;;;;N;;;;;
+110A9;KAITHI LETTER RA;Lo;0;L;;;;;N;;;;;
+110AA;KAITHI LETTER LA;Lo;0;L;;;;;N;;;;;
+110AB;KAITHI LETTER VA;Lo;0;L;110A5 110BA;;;;N;;;;;
+110AC;KAITHI LETTER SHA;Lo;0;L;;;;;N;;;;;
+110AD;KAITHI LETTER SSA;Lo;0;L;;;;;N;;;;;
+110AE;KAITHI LETTER SA;Lo;0;L;;;;;N;;;;;
+110AF;KAITHI LETTER HA;Lo;0;L;;;;;N;;;;;
+110B0;KAITHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+110B1;KAITHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
+110B2;KAITHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
+110B3;KAITHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+110B4;KAITHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+110B5;KAITHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+110B6;KAITHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+110B7;KAITHI VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
+110B8;KAITHI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+110B9;KAITHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+110BA;KAITHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+110BB;KAITHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
+110BC;KAITHI ENUMERATION SIGN;Po;0;L;;;;;N;;;;;
+110BD;KAITHI NUMBER SIGN;Cf;0;L;;;;;N;;;;;
+110BE;KAITHI SECTION MARK;Po;0;L;;;;;N;;;;;
+110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;;
+110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;;
+110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;;
+12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;;
+12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;;
+12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;;
+12003;CUNEIFORM SIGN A TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+12004;CUNEIFORM SIGN A TIMES HA;Lo;0;L;;;;;N;;;;;
+12005;CUNEIFORM SIGN A TIMES IGI;Lo;0;L;;;;;N;;;;;
+12006;CUNEIFORM SIGN A TIMES LAGAR GUNU;Lo;0;L;;;;;N;;;;;
+12007;CUNEIFORM SIGN A TIMES MUSH;Lo;0;L;;;;;N;;;;;
+12008;CUNEIFORM SIGN A TIMES SAG;Lo;0;L;;;;;N;;;;;
+12009;CUNEIFORM SIGN A2;Lo;0;L;;;;;N;;;;;
+1200A;CUNEIFORM SIGN AB;Lo;0;L;;;;;N;;;;;
+1200B;CUNEIFORM SIGN AB TIMES ASH2;Lo;0;L;;;;;N;;;;;
+1200C;CUNEIFORM SIGN AB TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;;
+1200D;CUNEIFORM SIGN AB TIMES GAL;Lo;0;L;;;;;N;;;;;
+1200E;CUNEIFORM SIGN AB TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+1200F;CUNEIFORM SIGN AB TIMES HA;Lo;0;L;;;;;N;;;;;
+12010;CUNEIFORM SIGN AB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+12011;CUNEIFORM SIGN AB TIMES IMIN;Lo;0;L;;;;;N;;;;;
+12012;CUNEIFORM SIGN AB TIMES LAGAB;Lo;0;L;;;;;N;;;;;
+12013;CUNEIFORM SIGN AB TIMES SHESH;Lo;0;L;;;;;N;;;;;
+12014;CUNEIFORM SIGN AB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;;
+12015;CUNEIFORM SIGN AB GUNU;Lo;0;L;;;;;N;;;;;
+12016;CUNEIFORM SIGN AB2;Lo;0;L;;;;;N;;;;;
+12017;CUNEIFORM SIGN AB2 TIMES BALAG;Lo;0;L;;;;;N;;;;;
+12018;CUNEIFORM SIGN AB2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+12019;CUNEIFORM SIGN AB2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
+1201A;CUNEIFORM SIGN AB2 TIMES SHA3;Lo;0;L;;;;;N;;;;;
+1201B;CUNEIFORM SIGN AB2 TIMES TAK4;Lo;0;L;;;;;N;;;;;
+1201C;CUNEIFORM SIGN AD;Lo;0;L;;;;;N;;;;;
+1201D;CUNEIFORM SIGN AK;Lo;0;L;;;;;N;;;;;
+1201E;CUNEIFORM SIGN AK TIMES ERIN2;Lo;0;L;;;;;N;;;;;
+1201F;CUNEIFORM SIGN AK TIMES SHITA PLUS GISH;Lo;0;L;;;;;N;;;;;
+12020;CUNEIFORM SIGN AL;Lo;0;L;;;;;N;;;;;
+12021;CUNEIFORM SIGN AL TIMES AL;Lo;0;L;;;;;N;;;;;
+12022;CUNEIFORM SIGN AL TIMES DIM2;Lo;0;L;;;;;N;;;;;
+12023;CUNEIFORM SIGN AL TIMES GISH;Lo;0;L;;;;;N;;;;;
+12024;CUNEIFORM SIGN AL TIMES HA;Lo;0;L;;;;;N;;;;;
+12025;CUNEIFORM SIGN AL TIMES KAD3;Lo;0;L;;;;;N;;;;;
+12026;CUNEIFORM SIGN AL TIMES KI;Lo;0;L;;;;;N;;;;;
+12027;CUNEIFORM SIGN AL TIMES SHE;Lo;0;L;;;;;N;;;;;
+12028;CUNEIFORM SIGN AL TIMES USH;Lo;0;L;;;;;N;;;;;
+12029;CUNEIFORM SIGN ALAN;Lo;0;L;;;;;N;;;;;
+1202A;CUNEIFORM SIGN ALEPH;Lo;0;L;;;;;N;;;;;
+1202B;CUNEIFORM SIGN AMAR;Lo;0;L;;;;;N;;;;;
+1202C;CUNEIFORM SIGN AMAR TIMES SHE;Lo;0;L;;;;;N;;;;;
+1202D;CUNEIFORM SIGN AN;Lo;0;L;;;;;N;;;;;
+1202E;CUNEIFORM SIGN AN OVER AN;Lo;0;L;;;;;N;;;;;
+1202F;CUNEIFORM SIGN AN THREE TIMES;Lo;0;L;;;;;N;;;;;
+12030;CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA;Lo;0;L;;;;;N;;;;;
+12031;CUNEIFORM SIGN AN PLUS NAGA SQUARED;Lo;0;L;;;;;N;;;;;
+12032;CUNEIFORM SIGN ANSHE;Lo;0;L;;;;;N;;;;;
+12033;CUNEIFORM SIGN APIN;Lo;0;L;;;;;N;;;;;
+12034;CUNEIFORM SIGN ARAD;Lo;0;L;;;;;N;;;;;
+12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;;
+12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;;
+12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;;
+12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;;N;;;;;
+12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;;N;;;;;
+1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;;
+1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;;
+1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;;
+1203D;CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;;
+1203E;CUNEIFORM SIGN ASH2;Lo;0;L;;;;;N;;;;;
+1203F;CUNEIFORM SIGN ASHGAB;Lo;0;L;;;;;N;;;;;
+12040;CUNEIFORM SIGN BA;Lo;0;L;;;;;N;;;;;
+12041;CUNEIFORM SIGN BAD;Lo;0;L;;;;;N;;;;;
+12042;CUNEIFORM SIGN BAG3;Lo;0;L;;;;;N;;;;;
+12043;CUNEIFORM SIGN BAHAR2;Lo;0;L;;;;;N;;;;;
+12044;CUNEIFORM SIGN BAL;Lo;0;L;;;;;N;;;;;
+12045;CUNEIFORM SIGN BAL OVER BAL;Lo;0;L;;;;;N;;;;;
+12046;CUNEIFORM SIGN BALAG;Lo;0;L;;;;;N;;;;;
+12047;CUNEIFORM SIGN BAR;Lo;0;L;;;;;N;;;;;
+12048;CUNEIFORM SIGN BARA2;Lo;0;L;;;;;N;;;;;
+12049;CUNEIFORM SIGN BI;Lo;0;L;;;;;N;;;;;
+1204A;CUNEIFORM SIGN BI TIMES A;Lo;0;L;;;;;N;;;;;
+1204B;CUNEIFORM SIGN BI TIMES GAR;Lo;0;L;;;;;N;;;;;
+1204C;CUNEIFORM SIGN BI TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+1204D;CUNEIFORM SIGN BU;Lo;0;L;;;;;N;;;;;
+1204E;CUNEIFORM SIGN BU OVER BU AB;Lo;0;L;;;;;N;;;;;
+1204F;CUNEIFORM SIGN BU OVER BU UN;Lo;0;L;;;;;N;;;;;
+12050;CUNEIFORM SIGN BU CROSSING BU;Lo;0;L;;;;;N;;;;;
+12051;CUNEIFORM SIGN BULUG;Lo;0;L;;;;;N;;;;;
+12052;CUNEIFORM SIGN BULUG OVER BULUG;Lo;0;L;;;;;N;;;;;
+12053;CUNEIFORM SIGN BUR;Lo;0;L;;;;;N;;;;;
+12054;CUNEIFORM SIGN BUR2;Lo;0;L;;;;;N;;;;;
+12055;CUNEIFORM SIGN DA;Lo;0;L;;;;;N;;;;;
+12056;CUNEIFORM SIGN DAG;Lo;0;L;;;;;N;;;;;
+12057;CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH;Lo;0;L;;;;;N;;;;;
+12058;CUNEIFORM SIGN DAG KISIM5 TIMES AMAR;Lo;0;L;;;;;N;;;;;
+12059;CUNEIFORM SIGN DAG KISIM5 TIMES BALAG;Lo;0;L;;;;;N;;;;;
+1205A;CUNEIFORM SIGN DAG KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;;
+1205B;CUNEIFORM SIGN DAG KISIM5 TIMES GA;Lo;0;L;;;;;N;;;;;
+1205C;CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH;Lo;0;L;;;;;N;;;;;
+1205D;CUNEIFORM SIGN DAG KISIM5 TIMES GI;Lo;0;L;;;;;N;;;;;
+1205E;CUNEIFORM SIGN DAG KISIM5 TIMES GIR2;Lo;0;L;;;;;N;;;;;
+1205F;CUNEIFORM SIGN DAG KISIM5 TIMES GUD;Lo;0;L;;;;;N;;;;;
+12060;CUNEIFORM SIGN DAG KISIM5 TIMES HA;Lo;0;L;;;;;N;;;;;
+12061;CUNEIFORM SIGN DAG KISIM5 TIMES IR;Lo;0;L;;;;;N;;;;;
+12062;CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU;Lo;0;L;;;;;N;;;;;
+12063;CUNEIFORM SIGN DAG KISIM5 TIMES KAK;Lo;0;L;;;;;N;;;;;
+12064;CUNEIFORM SIGN DAG KISIM5 TIMES LA;Lo;0;L;;;;;N;;;;;
+12065;CUNEIFORM SIGN DAG KISIM5 TIMES LU;Lo;0;L;;;;;N;;;;;
+12066;CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2;Lo;0;L;;;;;N;;;;;
+12067;CUNEIFORM SIGN DAG KISIM5 TIMES LUM;Lo;0;L;;;;;N;;;;;
+12068;CUNEIFORM SIGN DAG KISIM5 TIMES NE;Lo;0;L;;;;;N;;;;;
+12069;CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;;
+1206A;CUNEIFORM SIGN DAG KISIM5 TIMES SI;Lo;0;L;;;;;N;;;;;
+1206B;CUNEIFORM SIGN DAG KISIM5 TIMES TAK4;Lo;0;L;;;;;N;;;;;
+1206C;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2;Lo;0;L;;;;;N;;;;;
+1206D;CUNEIFORM SIGN DAG KISIM5 TIMES USH;Lo;0;L;;;;;N;;;;;
+1206E;CUNEIFORM SIGN DAM;Lo;0;L;;;;;N;;;;;
+1206F;CUNEIFORM SIGN DAR;Lo;0;L;;;;;N;;;;;
+12070;CUNEIFORM SIGN DARA3;Lo;0;L;;;;;N;;;;;
+12071;CUNEIFORM SIGN DARA4;Lo;0;L;;;;;N;;;;;
+12072;CUNEIFORM SIGN DI;Lo;0;L;;;;;N;;;;;
+12073;CUNEIFORM SIGN DIB;Lo;0;L;;;;;N;;;;;
+12074;CUNEIFORM SIGN DIM;Lo;0;L;;;;;N;;;;;
+12075;CUNEIFORM SIGN DIM TIMES SHE;Lo;0;L;;;;;N;;;;;
+12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;;
+12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;;
+12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;;
+12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;;N;;;;;
+1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;;
+1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;;
+1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;;
+1207D;CUNEIFORM SIGN DU SHESHIG;Lo;0;L;;;;;N;;;;;
+1207E;CUNEIFORM SIGN DUB;Lo;0;L;;;;;N;;;;;
+1207F;CUNEIFORM SIGN DUB TIMES ESH2;Lo;0;L;;;;;N;;;;;
+12080;CUNEIFORM SIGN DUB2;Lo;0;L;;;;;N;;;;;
+12081;CUNEIFORM SIGN DUG;Lo;0;L;;;;;N;;;;;
+12082;CUNEIFORM SIGN DUGUD;Lo;0;L;;;;;N;;;;;
+12083;CUNEIFORM SIGN DUH;Lo;0;L;;;;;N;;;;;
+12084;CUNEIFORM SIGN DUN;Lo;0;L;;;;;N;;;;;
+12085;CUNEIFORM SIGN DUN3;Lo;0;L;;;;;N;;;;;
+12086;CUNEIFORM SIGN DUN3 GUNU;Lo;0;L;;;;;N;;;;;
+12087;CUNEIFORM SIGN DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;;
+12088;CUNEIFORM SIGN DUN4;Lo;0;L;;;;;N;;;;;
+12089;CUNEIFORM SIGN DUR2;Lo;0;L;;;;;N;;;;;
+1208A;CUNEIFORM SIGN E;Lo;0;L;;;;;N;;;;;
+1208B;CUNEIFORM SIGN E TIMES PAP;Lo;0;L;;;;;N;;;;;
+1208C;CUNEIFORM SIGN E OVER E NUN OVER NUN;Lo;0;L;;;;;N;;;;;
+1208D;CUNEIFORM SIGN E2;Lo;0;L;;;;;N;;;;;
+1208E;CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA;Lo;0;L;;;;;N;;;;;
+1208F;CUNEIFORM SIGN E2 TIMES GAR;Lo;0;L;;;;;N;;;;;
+12090;CUNEIFORM SIGN E2 TIMES MI;Lo;0;L;;;;;N;;;;;
+12091;CUNEIFORM SIGN E2 TIMES SAL;Lo;0;L;;;;;N;;;;;
+12092;CUNEIFORM SIGN E2 TIMES SHE;Lo;0;L;;;;;N;;;;;
+12093;CUNEIFORM SIGN E2 TIMES U;Lo;0;L;;;;;N;;;;;
+12094;CUNEIFORM SIGN EDIN;Lo;0;L;;;;;N;;;;;
+12095;CUNEIFORM SIGN EGIR;Lo;0;L;;;;;N;;;;;
+12096;CUNEIFORM SIGN EL;Lo;0;L;;;;;N;;;;;
+12097;CUNEIFORM SIGN EN;Lo;0;L;;;;;N;;;;;
+12098;CUNEIFORM SIGN EN TIMES GAN2;Lo;0;L;;;;;N;;;;;
+12099;CUNEIFORM SIGN EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+1209A;CUNEIFORM SIGN EN TIMES ME;Lo;0;L;;;;;N;;;;;
+1209B;CUNEIFORM SIGN EN CROSSING EN;Lo;0;L;;;;;N;;;;;
+1209C;CUNEIFORM SIGN EN OPPOSING EN;Lo;0;L;;;;;N;;;;;
+1209D;CUNEIFORM SIGN EN SQUARED;Lo;0;L;;;;;N;;;;;
+1209E;CUNEIFORM SIGN EREN;Lo;0;L;;;;;N;;;;;
+1209F;CUNEIFORM SIGN ERIN2;Lo;0;L;;;;;N;;;;;
+120A0;CUNEIFORM SIGN ESH2;Lo;0;L;;;;;N;;;;;
+120A1;CUNEIFORM SIGN EZEN;Lo;0;L;;;;;N;;;;;
+120A2;CUNEIFORM SIGN EZEN TIMES A;Lo;0;L;;;;;N;;;;;
+120A3;CUNEIFORM SIGN EZEN TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;;
+120A4;CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL;Lo;0;L;;;;;N;;;;;
+120A5;CUNEIFORM SIGN EZEN TIMES AN;Lo;0;L;;;;;N;;;;;
+120A6;CUNEIFORM SIGN EZEN TIMES BAD;Lo;0;L;;;;;N;;;;;
+120A7;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;;
+120A8;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;;
+120A9;CUNEIFORM SIGN EZEN TIMES HA;Lo;0;L;;;;;N;;;;;
+120AA;CUNEIFORM SIGN EZEN TIMES HA GUNU;Lo;0;L;;;;;N;;;;;
+120AB;CUNEIFORM SIGN EZEN TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+120AC;CUNEIFORM SIGN EZEN TIMES KASKAL;Lo;0;L;;;;;N;;;;;
+120AD;CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED;Lo;0;L;;;;;N;;;;;
+120AE;CUNEIFORM SIGN EZEN TIMES KU3;Lo;0;L;;;;;N;;;;;
+120AF;CUNEIFORM SIGN EZEN TIMES LA;Lo;0;L;;;;;N;;;;;
+120B0;CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL;Lo;0;L;;;;;N;;;;;
+120B1;CUNEIFORM SIGN EZEN TIMES LI;Lo;0;L;;;;;N;;;;;
+120B2;CUNEIFORM SIGN EZEN TIMES LU;Lo;0;L;;;;;N;;;;;
+120B3;CUNEIFORM SIGN EZEN TIMES U2;Lo;0;L;;;;;N;;;;;
+120B4;CUNEIFORM SIGN EZEN TIMES UD;Lo;0;L;;;;;N;;;;;
+120B5;CUNEIFORM SIGN GA;Lo;0;L;;;;;N;;;;;
+120B6;CUNEIFORM SIGN GA GUNU;Lo;0;L;;;;;N;;;;;
+120B7;CUNEIFORM SIGN GA2;Lo;0;L;;;;;N;;;;;
+120B8;CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;;
+120B9;CUNEIFORM SIGN GA2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;;
+120BA;CUNEIFORM SIGN GA2 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;;
+120BB;CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB;Lo;0;L;;;;;N;;;;;
+120BC;CUNEIFORM SIGN GA2 TIMES AN;Lo;0;L;;;;;N;;;;;
+120BD;CUNEIFORM SIGN GA2 TIMES ASH;Lo;0;L;;;;;N;;;;;
+120BE;CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL;Lo;0;L;;;;;N;;;;;
+120BF;CUNEIFORM SIGN GA2 TIMES BAD;Lo;0;L;;;;;N;;;;;
+120C0;CUNEIFORM SIGN GA2 TIMES BAR PLUS RA;Lo;0;L;;;;;N;;;;;
+120C1;CUNEIFORM SIGN GA2 TIMES BUR;Lo;0;L;;;;;N;;;;;
+120C2;CUNEIFORM SIGN GA2 TIMES BUR PLUS RA;Lo;0;L;;;;;N;;;;;
+120C3;CUNEIFORM SIGN GA2 TIMES DA;Lo;0;L;;;;;N;;;;;
+120C4;CUNEIFORM SIGN GA2 TIMES DI;Lo;0;L;;;;;N;;;;;
+120C5;CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE;Lo;0;L;;;;;N;;;;;
+120C6;CUNEIFORM SIGN GA2 TIMES DUB;Lo;0;L;;;;;N;;;;;
+120C7;CUNEIFORM SIGN GA2 TIMES EL;Lo;0;L;;;;;N;;;;;
+120C8;CUNEIFORM SIGN GA2 TIMES EL PLUS LA;Lo;0;L;;;;;N;;;;;
+120C9;CUNEIFORM SIGN GA2 TIMES EN;Lo;0;L;;;;;N;;;;;
+120CA;CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+120CB;CUNEIFORM SIGN GA2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+120CC;CUNEIFORM SIGN GA2 TIMES GAR;Lo;0;L;;;;;N;;;;;
+120CD;CUNEIFORM SIGN GA2 TIMES GI;Lo;0;L;;;;;N;;;;;
+120CE;CUNEIFORM SIGN GA2 TIMES GI4;Lo;0;L;;;;;N;;;;;
+120CF;CUNEIFORM SIGN GA2 TIMES GI4 PLUS A;Lo;0;L;;;;;N;;;;;
+120D0;CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU;Lo;0;L;;;;;N;;;;;
+120D1;CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2;Lo;0;L;;;;;N;;;;;
+120D2;CUNEIFORM SIGN GA2 TIMES HAL;Lo;0;L;;;;;N;;;;;
+120D3;CUNEIFORM SIGN GA2 TIMES HAL PLUS LA;Lo;0;L;;;;;N;;;;;
+120D4;CUNEIFORM SIGN GA2 TIMES HI PLUS LI;Lo;0;L;;;;;N;;;;;
+120D5;CUNEIFORM SIGN GA2 TIMES HUB2;Lo;0;L;;;;;N;;;;;
+120D6;CUNEIFORM SIGN GA2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+120D7;CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH;Lo;0;L;;;;;N;;;;;
+120D8;CUNEIFORM SIGN GA2 TIMES KAK;Lo;0;L;;;;;N;;;;;
+120D9;CUNEIFORM SIGN GA2 TIMES KASKAL;Lo;0;L;;;;;N;;;;;
+120DA;CUNEIFORM SIGN GA2 TIMES KID;Lo;0;L;;;;;N;;;;;
+120DB;CUNEIFORM SIGN GA2 TIMES KID PLUS LAL;Lo;0;L;;;;;N;;;;;
+120DC;CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN;Lo;0;L;;;;;N;;;;;
+120DD;CUNEIFORM SIGN GA2 TIMES LA;Lo;0;L;;;;;N;;;;;
+120DE;CUNEIFORM SIGN GA2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
+120DF;CUNEIFORM SIGN GA2 TIMES MI;Lo;0;L;;;;;N;;;;;
+120E0;CUNEIFORM SIGN GA2 TIMES NUN;Lo;0;L;;;;;N;;;;;
+120E1;CUNEIFORM SIGN GA2 TIMES NUN OVER NUN;Lo;0;L;;;;;N;;;;;
+120E2;CUNEIFORM SIGN GA2 TIMES PA;Lo;0;L;;;;;N;;;;;
+120E3;CUNEIFORM SIGN GA2 TIMES SAL;Lo;0;L;;;;;N;;;;;
+120E4;CUNEIFORM SIGN GA2 TIMES SAR;Lo;0;L;;;;;N;;;;;
+120E5;CUNEIFORM SIGN GA2 TIMES SHE;Lo;0;L;;;;;N;;;;;
+120E6;CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR;Lo;0;L;;;;;N;;;;;
+120E7;CUNEIFORM SIGN GA2 TIMES SHID;Lo;0;L;;;;;N;;;;;
+120E8;CUNEIFORM SIGN GA2 TIMES SUM;Lo;0;L;;;;;N;;;;;
+120E9;CUNEIFORM SIGN GA2 TIMES TAK4;Lo;0;L;;;;;N;;;;;
+120EA;CUNEIFORM SIGN GA2 TIMES U;Lo;0;L;;;;;N;;;;;
+120EB;CUNEIFORM SIGN GA2 TIMES UD;Lo;0;L;;;;;N;;;;;
+120EC;CUNEIFORM SIGN GA2 TIMES UD PLUS DU;Lo;0;L;;;;;N;;;;;
+120ED;CUNEIFORM SIGN GA2 OVER GA2;Lo;0;L;;;;;N;;;;;
+120EE;CUNEIFORM SIGN GABA;Lo;0;L;;;;;N;;;;;
+120EF;CUNEIFORM SIGN GABA CROSSING GABA;Lo;0;L;;;;;N;;;;;
+120F0;CUNEIFORM SIGN GAD;Lo;0;L;;;;;N;;;;;
+120F1;CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
+120F2;CUNEIFORM SIGN GAL;Lo;0;L;;;;;N;;;;;
+120F3;CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
+120F4;CUNEIFORM SIGN GALAM;Lo;0;L;;;;;N;;;;;
+120F5;CUNEIFORM SIGN GAM;Lo;0;L;;;;;N;;;;;
+120F6;CUNEIFORM SIGN GAN;Lo;0;L;;;;;N;;;;;
+120F7;CUNEIFORM SIGN GAN2;Lo;0;L;;;;;N;;;;;
+120F8;CUNEIFORM SIGN GAN2 TENU;Lo;0;L;;;;;N;;;;;
+120F9;CUNEIFORM SIGN GAN2 OVER GAN2;Lo;0;L;;;;;N;;;;;
+120FA;CUNEIFORM SIGN GAN2 CROSSING GAN2;Lo;0;L;;;;;N;;;;;
+120FB;CUNEIFORM SIGN GAR;Lo;0;L;;;;;N;;;;;
+120FC;CUNEIFORM SIGN GAR3;Lo;0;L;;;;;N;;;;;
+120FD;CUNEIFORM SIGN GASHAN;Lo;0;L;;;;;N;;;;;
+120FE;CUNEIFORM SIGN GESHTIN;Lo;0;L;;;;;N;;;;;
+120FF;CUNEIFORM SIGN GESHTIN TIMES KUR;Lo;0;L;;;;;N;;;;;
+12100;CUNEIFORM SIGN GI;Lo;0;L;;;;;N;;;;;
+12101;CUNEIFORM SIGN GI TIMES E;Lo;0;L;;;;;N;;;;;
+12102;CUNEIFORM SIGN GI TIMES U;Lo;0;L;;;;;N;;;;;
+12103;CUNEIFORM SIGN GI CROSSING GI;Lo;0;L;;;;;N;;;;;
+12104;CUNEIFORM SIGN GI4;Lo;0;L;;;;;N;;;;;
+12105;CUNEIFORM SIGN GI4 OVER GI4;Lo;0;L;;;;;N;;;;;
+12106;CUNEIFORM SIGN GI4 CROSSING GI4;Lo;0;L;;;;;N;;;;;
+12107;CUNEIFORM SIGN GIDIM;Lo;0;L;;;;;N;;;;;
+12108;CUNEIFORM SIGN GIR2;Lo;0;L;;;;;N;;;;;
+12109;CUNEIFORM SIGN GIR2 GUNU;Lo;0;L;;;;;N;;;;;
+1210A;CUNEIFORM SIGN GIR3;Lo;0;L;;;;;N;;;;;
+1210B;CUNEIFORM SIGN GIR3 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;;
+1210C;CUNEIFORM SIGN GIR3 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+1210D;CUNEIFORM SIGN GIR3 TIMES IGI;Lo;0;L;;;;;N;;;;;
+1210E;CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI;Lo;0;L;;;;;N;;;;;
+1210F;CUNEIFORM SIGN GIR3 TIMES PA;Lo;0;L;;;;;N;;;;;
+12110;CUNEIFORM SIGN GISAL;Lo;0;L;;;;;N;;;;;
+12111;CUNEIFORM SIGN GISH;Lo;0;L;;;;;N;;;;;
+12112;CUNEIFORM SIGN GISH CROSSING GISH;Lo;0;L;;;;;N;;;;;
+12113;CUNEIFORM SIGN GISH TIMES BAD;Lo;0;L;;;;;N;;;;;
+12114;CUNEIFORM SIGN GISH TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12115;CUNEIFORM SIGN GISH TENU;Lo;0;L;;;;;N;;;;;
+12116;CUNEIFORM SIGN GU;Lo;0;L;;;;;N;;;;;
+12117;CUNEIFORM SIGN GU CROSSING GU;Lo;0;L;;;;;N;;;;;
+12118;CUNEIFORM SIGN GU2;Lo;0;L;;;;;N;;;;;
+12119;CUNEIFORM SIGN GU2 TIMES KAK;Lo;0;L;;;;;N;;;;;
+1211A;CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+1211B;CUNEIFORM SIGN GU2 TIMES NUN;Lo;0;L;;;;;N;;;;;
+1211C;CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2;Lo;0;L;;;;;N;;;;;
+1211D;CUNEIFORM SIGN GU2 GUNU;Lo;0;L;;;;;N;;;;;
+1211E;CUNEIFORM SIGN GUD;Lo;0;L;;;;;N;;;;;
+1211F;CUNEIFORM SIGN GUD TIMES A PLUS KUR;Lo;0;L;;;;;N;;;;;
+12120;CUNEIFORM SIGN GUD TIMES KUR;Lo;0;L;;;;;N;;;;;
+12121;CUNEIFORM SIGN GUD OVER GUD LUGAL;Lo;0;L;;;;;N;;;;;
+12122;CUNEIFORM SIGN GUL;Lo;0;L;;;;;N;;;;;
+12123;CUNEIFORM SIGN GUM;Lo;0;L;;;;;N;;;;;
+12124;CUNEIFORM SIGN GUM TIMES SHE;Lo;0;L;;;;;N;;;;;
+12125;CUNEIFORM SIGN GUR;Lo;0;L;;;;;N;;;;;
+12126;CUNEIFORM SIGN GUR7;Lo;0;L;;;;;N;;;;;
+12127;CUNEIFORM SIGN GURUN;Lo;0;L;;;;;N;;;;;
+12128;CUNEIFORM SIGN GURUSH;Lo;0;L;;;;;N;;;;;
+12129;CUNEIFORM SIGN HA;Lo;0;L;;;;;N;;;;;
+1212A;CUNEIFORM SIGN HA TENU;Lo;0;L;;;;;N;;;;;
+1212B;CUNEIFORM SIGN HA GUNU;Lo;0;L;;;;;N;;;;;
+1212C;CUNEIFORM SIGN HAL;Lo;0;L;;;;;N;;;;;
+1212D;CUNEIFORM SIGN HI;Lo;0;L;;;;;N;;;;;
+1212E;CUNEIFORM SIGN HI TIMES ASH;Lo;0;L;;;;;N;;;;;
+1212F;CUNEIFORM SIGN HI TIMES ASH2;Lo;0;L;;;;;N;;;;;
+12130;CUNEIFORM SIGN HI TIMES BAD;Lo;0;L;;;;;N;;;;;
+12131;CUNEIFORM SIGN HI TIMES DISH;Lo;0;L;;;;;N;;;;;
+12132;CUNEIFORM SIGN HI TIMES GAD;Lo;0;L;;;;;N;;;;;
+12133;CUNEIFORM SIGN HI TIMES KIN;Lo;0;L;;;;;N;;;;;
+12134;CUNEIFORM SIGN HI TIMES NUN;Lo;0;L;;;;;N;;;;;
+12135;CUNEIFORM SIGN HI TIMES SHE;Lo;0;L;;;;;N;;;;;
+12136;CUNEIFORM SIGN HI TIMES U;Lo;0;L;;;;;N;;;;;
+12137;CUNEIFORM SIGN HU;Lo;0;L;;;;;N;;;;;
+12138;CUNEIFORM SIGN HUB2;Lo;0;L;;;;;N;;;;;
+12139;CUNEIFORM SIGN HUB2 TIMES AN;Lo;0;L;;;;;N;;;;;
+1213A;CUNEIFORM SIGN HUB2 TIMES HAL;Lo;0;L;;;;;N;;;;;
+1213B;CUNEIFORM SIGN HUB2 TIMES KASKAL;Lo;0;L;;;;;N;;;;;
+1213C;CUNEIFORM SIGN HUB2 TIMES LISH;Lo;0;L;;;;;N;;;;;
+1213D;CUNEIFORM SIGN HUB2 TIMES UD;Lo;0;L;;;;;N;;;;;
+1213E;CUNEIFORM SIGN HUL2;Lo;0;L;;;;;N;;;;;
+1213F;CUNEIFORM SIGN I;Lo;0;L;;;;;N;;;;;
+12140;CUNEIFORM SIGN I A;Lo;0;L;;;;;N;;;;;
+12141;CUNEIFORM SIGN IB;Lo;0;L;;;;;N;;;;;
+12142;CUNEIFORM SIGN IDIM;Lo;0;L;;;;;N;;;;;
+12143;CUNEIFORM SIGN IDIM OVER IDIM BUR;Lo;0;L;;;;;N;;;;;
+12144;CUNEIFORM SIGN IDIM OVER IDIM SQUARED;Lo;0;L;;;;;N;;;;;
+12145;CUNEIFORM SIGN IG;Lo;0;L;;;;;N;;;;;
+12146;CUNEIFORM SIGN IGI;Lo;0;L;;;;;N;;;;;
+12147;CUNEIFORM SIGN IGI DIB;Lo;0;L;;;;;N;;;;;
+12148;CUNEIFORM SIGN IGI RI;Lo;0;L;;;;;N;;;;;
+12149;CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD;Lo;0;L;;;;;N;;;;;
+1214A;CUNEIFORM SIGN IGI GUNU;Lo;0;L;;;;;N;;;;;
+1214B;CUNEIFORM SIGN IL;Lo;0;L;;;;;N;;;;;
+1214C;CUNEIFORM SIGN IL TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+1214D;CUNEIFORM SIGN IL2;Lo;0;L;;;;;N;;;;;
+1214E;CUNEIFORM SIGN IM;Lo;0;L;;;;;N;;;;;
+1214F;CUNEIFORM SIGN IM TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12150;CUNEIFORM SIGN IM CROSSING IM;Lo;0;L;;;;;N;;;;;
+12151;CUNEIFORM SIGN IM OPPOSING IM;Lo;0;L;;;;;N;;;;;
+12152;CUNEIFORM SIGN IM SQUARED;Lo;0;L;;;;;N;;;;;
+12153;CUNEIFORM SIGN IMIN;Lo;0;L;;;;;N;;;;;
+12154;CUNEIFORM SIGN IN;Lo;0;L;;;;;N;;;;;
+12155;CUNEIFORM SIGN IR;Lo;0;L;;;;;N;;;;;
+12156;CUNEIFORM SIGN ISH;Lo;0;L;;;;;N;;;;;
+12157;CUNEIFORM SIGN KA;Lo;0;L;;;;;N;;;;;
+12158;CUNEIFORM SIGN KA TIMES A;Lo;0;L;;;;;N;;;;;
+12159;CUNEIFORM SIGN KA TIMES AD;Lo;0;L;;;;;N;;;;;
+1215A;CUNEIFORM SIGN KA TIMES AD PLUS KU3;Lo;0;L;;;;;N;;;;;
+1215B;CUNEIFORM SIGN KA TIMES ASH2;Lo;0;L;;;;;N;;;;;
+1215C;CUNEIFORM SIGN KA TIMES BAD;Lo;0;L;;;;;N;;;;;
+1215D;CUNEIFORM SIGN KA TIMES BALAG;Lo;0;L;;;;;N;;;;;
+1215E;CUNEIFORM SIGN KA TIMES BAR;Lo;0;L;;;;;N;;;;;
+1215F;CUNEIFORM SIGN KA TIMES BI;Lo;0;L;;;;;N;;;;;
+12160;CUNEIFORM SIGN KA TIMES ERIN2;Lo;0;L;;;;;N;;;;;
+12161;CUNEIFORM SIGN KA TIMES ESH2;Lo;0;L;;;;;N;;;;;
+12162;CUNEIFORM SIGN KA TIMES GA;Lo;0;L;;;;;N;;;;;
+12163;CUNEIFORM SIGN KA TIMES GAL;Lo;0;L;;;;;N;;;;;
+12164;CUNEIFORM SIGN KA TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+12165;CUNEIFORM SIGN KA TIMES GAR;Lo;0;L;;;;;N;;;;;
+12166;CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A;Lo;0;L;;;;;N;;;;;
+12167;CUNEIFORM SIGN KA TIMES GI;Lo;0;L;;;;;N;;;;;
+12168;CUNEIFORM SIGN KA TIMES GIR2;Lo;0;L;;;;;N;;;;;
+12169;CUNEIFORM SIGN KA TIMES GISH PLUS SAR;Lo;0;L;;;;;N;;;;;
+1216A;CUNEIFORM SIGN KA TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;;
+1216B;CUNEIFORM SIGN KA TIMES GU;Lo;0;L;;;;;N;;;;;
+1216C;CUNEIFORM SIGN KA TIMES GUR7;Lo;0;L;;;;;N;;;;;
+1216D;CUNEIFORM SIGN KA TIMES IGI;Lo;0;L;;;;;N;;;;;
+1216E;CUNEIFORM SIGN KA TIMES IM;Lo;0;L;;;;;N;;;;;
+1216F;CUNEIFORM SIGN KA TIMES KAK;Lo;0;L;;;;;N;;;;;
+12170;CUNEIFORM SIGN KA TIMES KI;Lo;0;L;;;;;N;;;;;
+12171;CUNEIFORM SIGN KA TIMES KID;Lo;0;L;;;;;N;;;;;
+12172;CUNEIFORM SIGN KA TIMES LI;Lo;0;L;;;;;N;;;;;
+12173;CUNEIFORM SIGN KA TIMES LU;Lo;0;L;;;;;N;;;;;
+12174;CUNEIFORM SIGN KA TIMES ME;Lo;0;L;;;;;N;;;;;
+12175;CUNEIFORM SIGN KA TIMES ME PLUS DU;Lo;0;L;;;;;N;;;;;
+12176;CUNEIFORM SIGN KA TIMES ME PLUS GI;Lo;0;L;;;;;N;;;;;
+12177;CUNEIFORM SIGN KA TIMES ME PLUS TE;Lo;0;L;;;;;N;;;;;
+12178;CUNEIFORM SIGN KA TIMES MI;Lo;0;L;;;;;N;;;;;
+12179;CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ;Lo;0;L;;;;;N;;;;;
+1217A;CUNEIFORM SIGN KA TIMES NE;Lo;0;L;;;;;N;;;;;
+1217B;CUNEIFORM SIGN KA TIMES NUN;Lo;0;L;;;;;N;;;;;
+1217C;CUNEIFORM SIGN KA TIMES PI;Lo;0;L;;;;;N;;;;;
+1217D;CUNEIFORM SIGN KA TIMES RU;Lo;0;L;;;;;N;;;;;
+1217E;CUNEIFORM SIGN KA TIMES SA;Lo;0;L;;;;;N;;;;;
+1217F;CUNEIFORM SIGN KA TIMES SAR;Lo;0;L;;;;;N;;;;;
+12180;CUNEIFORM SIGN KA TIMES SHA;Lo;0;L;;;;;N;;;;;
+12181;CUNEIFORM SIGN KA TIMES SHE;Lo;0;L;;;;;N;;;;;
+12182;CUNEIFORM SIGN KA TIMES SHID;Lo;0;L;;;;;N;;;;;
+12183;CUNEIFORM SIGN KA TIMES SHU;Lo;0;L;;;;;N;;;;;
+12184;CUNEIFORM SIGN KA TIMES SIG;Lo;0;L;;;;;N;;;;;
+12185;CUNEIFORM SIGN KA TIMES SUHUR;Lo;0;L;;;;;N;;;;;
+12186;CUNEIFORM SIGN KA TIMES TAR;Lo;0;L;;;;;N;;;;;
+12187;CUNEIFORM SIGN KA TIMES U;Lo;0;L;;;;;N;;;;;
+12188;CUNEIFORM SIGN KA TIMES U2;Lo;0;L;;;;;N;;;;;
+12189;CUNEIFORM SIGN KA TIMES UD;Lo;0;L;;;;;N;;;;;
+1218A;CUNEIFORM SIGN KA TIMES UMUM TIMES PA;Lo;0;L;;;;;N;;;;;
+1218B;CUNEIFORM SIGN KA TIMES USH;Lo;0;L;;;;;N;;;;;
+1218C;CUNEIFORM SIGN KA TIMES ZI;Lo;0;L;;;;;N;;;;;
+1218D;CUNEIFORM SIGN KA2;Lo;0;L;;;;;N;;;;;
+1218E;CUNEIFORM SIGN KA2 CROSSING KA2;Lo;0;L;;;;;N;;;;;
+1218F;CUNEIFORM SIGN KAB;Lo;0;L;;;;;N;;;;;
+12190;CUNEIFORM SIGN KAD2;Lo;0;L;;;;;N;;;;;
+12191;CUNEIFORM SIGN KAD3;Lo;0;L;;;;;N;;;;;
+12192;CUNEIFORM SIGN KAD4;Lo;0;L;;;;;N;;;;;
+12193;CUNEIFORM SIGN KAD5;Lo;0;L;;;;;N;;;;;
+12194;CUNEIFORM SIGN KAD5 OVER KAD5;Lo;0;L;;;;;N;;;;;
+12195;CUNEIFORM SIGN KAK;Lo;0;L;;;;;N;;;;;
+12196;CUNEIFORM SIGN KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+12197;CUNEIFORM SIGN KAL;Lo;0;L;;;;;N;;;;;
+12198;CUNEIFORM SIGN KAL TIMES BAD;Lo;0;L;;;;;N;;;;;
+12199;CUNEIFORM SIGN KAL CROSSING KAL;Lo;0;L;;;;;N;;;;;
+1219A;CUNEIFORM SIGN KAM2;Lo;0;L;;;;;N;;;;;
+1219B;CUNEIFORM SIGN KAM4;Lo;0;L;;;;;N;;;;;
+1219C;CUNEIFORM SIGN KASKAL;Lo;0;L;;;;;N;;;;;
+1219D;CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;;
+1219E;CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;;
+1219F;CUNEIFORM SIGN KESH2;Lo;0;L;;;;;N;;;;;
+121A0;CUNEIFORM SIGN KI;Lo;0;L;;;;;N;;;;;
+121A1;CUNEIFORM SIGN KI TIMES BAD;Lo;0;L;;;;;N;;;;;
+121A2;CUNEIFORM SIGN KI TIMES U;Lo;0;L;;;;;N;;;;;
+121A3;CUNEIFORM SIGN KI TIMES UD;Lo;0;L;;;;;N;;;;;
+121A4;CUNEIFORM SIGN KID;Lo;0;L;;;;;N;;;;;
+121A5;CUNEIFORM SIGN KIN;Lo;0;L;;;;;N;;;;;
+121A6;CUNEIFORM SIGN KISAL;Lo;0;L;;;;;N;;;;;
+121A7;CUNEIFORM SIGN KISH;Lo;0;L;;;;;N;;;;;
+121A8;CUNEIFORM SIGN KISIM5;Lo;0;L;;;;;N;;;;;
+121A9;CUNEIFORM SIGN KISIM5 OVER KISIM5;Lo;0;L;;;;;N;;;;;
+121AA;CUNEIFORM SIGN KU;Lo;0;L;;;;;N;;;;;
+121AB;CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2;Lo;0;L;;;;;N;;;;;
+121AC;CUNEIFORM SIGN KU3;Lo;0;L;;;;;N;;;;;
+121AD;CUNEIFORM SIGN KU4;Lo;0;L;;;;;N;;;;;
+121AE;CUNEIFORM SIGN KU4 VARIANT FORM;Lo;0;L;;;;;N;;;;;
+121AF;CUNEIFORM SIGN KU7;Lo;0;L;;;;;N;;;;;
+121B0;CUNEIFORM SIGN KUL;Lo;0;L;;;;;N;;;;;
+121B1;CUNEIFORM SIGN KUL GUNU;Lo;0;L;;;;;N;;;;;
+121B2;CUNEIFORM SIGN KUN;Lo;0;L;;;;;N;;;;;
+121B3;CUNEIFORM SIGN KUR;Lo;0;L;;;;;N;;;;;
+121B4;CUNEIFORM SIGN KUR OPPOSING KUR;Lo;0;L;;;;;N;;;;;
+121B5;CUNEIFORM SIGN KUSHU2;Lo;0;L;;;;;N;;;;;
+121B6;CUNEIFORM SIGN KWU318;Lo;0;L;;;;;N;;;;;
+121B7;CUNEIFORM SIGN LA;Lo;0;L;;;;;N;;;;;
+121B8;CUNEIFORM SIGN LAGAB;Lo;0;L;;;;;N;;;;;
+121B9;CUNEIFORM SIGN LAGAB TIMES A;Lo;0;L;;;;;N;;;;;
+121BA;CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;;
+121BB;CUNEIFORM SIGN LAGAB TIMES A PLUS GAR;Lo;0;L;;;;;N;;;;;
+121BC;CUNEIFORM SIGN LAGAB TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;;
+121BD;CUNEIFORM SIGN LAGAB TIMES AL;Lo;0;L;;;;;N;;;;;
+121BE;CUNEIFORM SIGN LAGAB TIMES AN;Lo;0;L;;;;;N;;;;;
+121BF;CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU;Lo;0;L;;;;;N;;;;;
+121C0;CUNEIFORM SIGN LAGAB TIMES BAD;Lo;0;L;;;;;N;;;;;
+121C1;CUNEIFORM SIGN LAGAB TIMES BI;Lo;0;L;;;;;N;;;;;
+121C2;CUNEIFORM SIGN LAGAB TIMES DAR;Lo;0;L;;;;;N;;;;;
+121C3;CUNEIFORM SIGN LAGAB TIMES EN;Lo;0;L;;;;;N;;;;;
+121C4;CUNEIFORM SIGN LAGAB TIMES GA;Lo;0;L;;;;;N;;;;;
+121C5;CUNEIFORM SIGN LAGAB TIMES GAR;Lo;0;L;;;;;N;;;;;
+121C6;CUNEIFORM SIGN LAGAB TIMES GUD;Lo;0;L;;;;;N;;;;;
+121C7;CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD;Lo;0;L;;;;;N;;;;;
+121C8;CUNEIFORM SIGN LAGAB TIMES HA;Lo;0;L;;;;;N;;;;;
+121C9;CUNEIFORM SIGN LAGAB TIMES HAL;Lo;0;L;;;;;N;;;;;
+121CA;CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN;Lo;0;L;;;;;N;;;;;
+121CB;CUNEIFORM SIGN LAGAB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+121CC;CUNEIFORM SIGN LAGAB TIMES IM;Lo;0;L;;;;;N;;;;;
+121CD;CUNEIFORM SIGN LAGAB TIMES IM PLUS HA;Lo;0;L;;;;;N;;;;;
+121CE;CUNEIFORM SIGN LAGAB TIMES IM PLUS LU;Lo;0;L;;;;;N;;;;;
+121CF;CUNEIFORM SIGN LAGAB TIMES KI;Lo;0;L;;;;;N;;;;;
+121D0;CUNEIFORM SIGN LAGAB TIMES KIN;Lo;0;L;;;;;N;;;;;
+121D1;CUNEIFORM SIGN LAGAB TIMES KU3;Lo;0;L;;;;;N;;;;;
+121D2;CUNEIFORM SIGN LAGAB TIMES KUL;Lo;0;L;;;;;N;;;;;
+121D3;CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A;Lo;0;L;;;;;N;;;;;
+121D4;CUNEIFORM SIGN LAGAB TIMES LAGAB;Lo;0;L;;;;;N;;;;;
+121D5;CUNEIFORM SIGN LAGAB TIMES LISH;Lo;0;L;;;;;N;;;;;
+121D6;CUNEIFORM SIGN LAGAB TIMES LU;Lo;0;L;;;;;N;;;;;
+121D7;CUNEIFORM SIGN LAGAB TIMES LUL;Lo;0;L;;;;;N;;;;;
+121D8;CUNEIFORM SIGN LAGAB TIMES ME;Lo;0;L;;;;;N;;;;;
+121D9;CUNEIFORM SIGN LAGAB TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
+121DA;CUNEIFORM SIGN LAGAB TIMES MUSH;Lo;0;L;;;;;N;;;;;
+121DB;CUNEIFORM SIGN LAGAB TIMES NE;Lo;0;L;;;;;N;;;;;
+121DC;CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;;
+121DD;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2;Lo;0;L;;;;;N;;;;;
+121DE;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU;Lo;0;L;;;;;N;;;;;
+121DF;CUNEIFORM SIGN LAGAB TIMES SHU2;Lo;0;L;;;;;N;;;;;
+121E0;CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2;Lo;0;L;;;;;N;;;;;
+121E1;CUNEIFORM SIGN LAGAB TIMES SUM;Lo;0;L;;;;;N;;;;;
+121E2;CUNEIFORM SIGN LAGAB TIMES TAG;Lo;0;L;;;;;N;;;;;
+121E3;CUNEIFORM SIGN LAGAB TIMES TAK4;Lo;0;L;;;;;N;;;;;
+121E4;CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA;Lo;0;L;;;;;N;;;;;
+121E5;CUNEIFORM SIGN LAGAB TIMES U;Lo;0;L;;;;;N;;;;;
+121E6;CUNEIFORM SIGN LAGAB TIMES U PLUS A;Lo;0;L;;;;;N;;;;;
+121E7;CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;;
+121E8;CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;;
+121E9;CUNEIFORM SIGN LAGAB TIMES UD;Lo;0;L;;;;;N;;;;;
+121EA;CUNEIFORM SIGN LAGAB TIMES USH;Lo;0;L;;;;;N;;;;;
+121EB;CUNEIFORM SIGN LAGAB SQUARED;Lo;0;L;;;;;N;;;;;
+121EC;CUNEIFORM SIGN LAGAR;Lo;0;L;;;;;N;;;;;
+121ED;CUNEIFORM SIGN LAGAR TIMES SHE;Lo;0;L;;;;;N;;;;;
+121EE;CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;;
+121EF;CUNEIFORM SIGN LAGAR GUNU;Lo;0;L;;;;;N;;;;;
+121F0;CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE;Lo;0;L;;;;;N;;;;;
+121F1;CUNEIFORM SIGN LAHSHU;Lo;0;L;;;;;N;;;;;
+121F2;CUNEIFORM SIGN LAL;Lo;0;L;;;;;N;;;;;
+121F3;CUNEIFORM SIGN LAL TIMES LAL;Lo;0;L;;;;;N;;;;;
+121F4;CUNEIFORM SIGN LAM;Lo;0;L;;;;;N;;;;;
+121F5;CUNEIFORM SIGN LAM TIMES KUR;Lo;0;L;;;;;N;;;;;
+121F6;CUNEIFORM SIGN LAM TIMES KUR PLUS RU;Lo;0;L;;;;;N;;;;;
+121F7;CUNEIFORM SIGN LI;Lo;0;L;;;;;N;;;;;
+121F8;CUNEIFORM SIGN LIL;Lo;0;L;;;;;N;;;;;
+121F9;CUNEIFORM SIGN LIMMU2;Lo;0;L;;;;;N;;;;;
+121FA;CUNEIFORM SIGN LISH;Lo;0;L;;;;;N;;;;;
+121FB;CUNEIFORM SIGN LU;Lo;0;L;;;;;N;;;;;
+121FC;CUNEIFORM SIGN LU TIMES BAD;Lo;0;L;;;;;N;;;;;
+121FD;CUNEIFORM SIGN LU2;Lo;0;L;;;;;N;;;;;
+121FE;CUNEIFORM SIGN LU2 TIMES AL;Lo;0;L;;;;;N;;;;;
+121FF;CUNEIFORM SIGN LU2 TIMES BAD;Lo;0;L;;;;;N;;;;;
+12200;CUNEIFORM SIGN LU2 TIMES ESH2;Lo;0;L;;;;;N;;;;;
+12201;CUNEIFORM SIGN LU2 TIMES ESH2 TENU;Lo;0;L;;;;;N;;;;;
+12202;CUNEIFORM SIGN LU2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+12203;CUNEIFORM SIGN LU2 TIMES HI TIMES BAD;Lo;0;L;;;;;N;;;;;
+12204;CUNEIFORM SIGN LU2 TIMES IM;Lo;0;L;;;;;N;;;;;
+12205;CUNEIFORM SIGN LU2 TIMES KAD2;Lo;0;L;;;;;N;;;;;
+12206;CUNEIFORM SIGN LU2 TIMES KAD3;Lo;0;L;;;;;N;;;;;
+12207;CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH;Lo;0;L;;;;;N;;;;;
+12208;CUNEIFORM SIGN LU2 TIMES KI;Lo;0;L;;;;;N;;;;;
+12209;CUNEIFORM SIGN LU2 TIMES LA PLUS ASH;Lo;0;L;;;;;N;;;;;
+1220A;CUNEIFORM SIGN LU2 TIMES LAGAB;Lo;0;L;;;;;N;;;;;
+1220B;CUNEIFORM SIGN LU2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;;
+1220C;CUNEIFORM SIGN LU2 TIMES NE;Lo;0;L;;;;;N;;;;;
+1220D;CUNEIFORM SIGN LU2 TIMES NU;Lo;0;L;;;;;N;;;;;
+1220E;CUNEIFORM SIGN LU2 TIMES SI PLUS ASH;Lo;0;L;;;;;N;;;;;
+1220F;CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU;Lo;0;L;;;;;N;;;;;
+12210;CUNEIFORM SIGN LU2 TIMES TUG2;Lo;0;L;;;;;N;;;;;
+12211;CUNEIFORM SIGN LU2 TENU;Lo;0;L;;;;;N;;;;;
+12212;CUNEIFORM SIGN LU2 CROSSING LU2;Lo;0;L;;;;;N;;;;;
+12213;CUNEIFORM SIGN LU2 OPPOSING LU2;Lo;0;L;;;;;N;;;;;
+12214;CUNEIFORM SIGN LU2 SQUARED;Lo;0;L;;;;;N;;;;;
+12215;CUNEIFORM SIGN LU2 SHESHIG;Lo;0;L;;;;;N;;;;;
+12216;CUNEIFORM SIGN LU3;Lo;0;L;;;;;N;;;;;
+12217;CUNEIFORM SIGN LUGAL;Lo;0;L;;;;;N;;;;;
+12218;CUNEIFORM SIGN LUGAL OVER LUGAL;Lo;0;L;;;;;N;;;;;
+12219;CUNEIFORM SIGN LUGAL OPPOSING LUGAL;Lo;0;L;;;;;N;;;;;
+1221A;CUNEIFORM SIGN LUGAL SHESHIG;Lo;0;L;;;;;N;;;;;
+1221B;CUNEIFORM SIGN LUH;Lo;0;L;;;;;N;;;;;
+1221C;CUNEIFORM SIGN LUL;Lo;0;L;;;;;N;;;;;
+1221D;CUNEIFORM SIGN LUM;Lo;0;L;;;;;N;;;;;
+1221E;CUNEIFORM SIGN LUM OVER LUM;Lo;0;L;;;;;N;;;;;
+1221F;CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR;Lo;0;L;;;;;N;;;;;
+12220;CUNEIFORM SIGN MA;Lo;0;L;;;;;N;;;;;
+12221;CUNEIFORM SIGN MA TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12222;CUNEIFORM SIGN MA GUNU;Lo;0;L;;;;;N;;;;;
+12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;;
+12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;;
+12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;;
+12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;;N;;;;;
+12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;;
+12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;;
+12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;;
+1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;;
+1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;;N;;;;;
+1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;;
+1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;;
+1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;;
+1222F;CUNEIFORM SIGN MUG GUNU;Lo;0;L;;;;;N;;;;;
+12230;CUNEIFORM SIGN MUNSUB;Lo;0;L;;;;;N;;;;;
+12231;CUNEIFORM SIGN MURGU2;Lo;0;L;;;;;N;;;;;
+12232;CUNEIFORM SIGN MUSH;Lo;0;L;;;;;N;;;;;
+12233;CUNEIFORM SIGN MUSH TIMES A;Lo;0;L;;;;;N;;;;;
+12234;CUNEIFORM SIGN MUSH TIMES KUR;Lo;0;L;;;;;N;;;;;
+12235;CUNEIFORM SIGN MUSH TIMES ZA;Lo;0;L;;;;;N;;;;;
+12236;CUNEIFORM SIGN MUSH OVER MUSH;Lo;0;L;;;;;N;;;;;
+12237;CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA;Lo;0;L;;;;;N;;;;;
+12238;CUNEIFORM SIGN MUSH CROSSING MUSH;Lo;0;L;;;;;N;;;;;
+12239;CUNEIFORM SIGN MUSH3;Lo;0;L;;;;;N;;;;;
+1223A;CUNEIFORM SIGN MUSH3 TIMES A;Lo;0;L;;;;;N;;;;;
+1223B;CUNEIFORM SIGN MUSH3 TIMES A PLUS DI;Lo;0;L;;;;;N;;;;;
+1223C;CUNEIFORM SIGN MUSH3 TIMES DI;Lo;0;L;;;;;N;;;;;
+1223D;CUNEIFORM SIGN MUSH3 GUNU;Lo;0;L;;;;;N;;;;;
+1223E;CUNEIFORM SIGN NA;Lo;0;L;;;;;N;;;;;
+1223F;CUNEIFORM SIGN NA2;Lo;0;L;;;;;N;;;;;
+12240;CUNEIFORM SIGN NAGA;Lo;0;L;;;;;N;;;;;
+12241;CUNEIFORM SIGN NAGA INVERTED;Lo;0;L;;;;;N;;;;;
+12242;CUNEIFORM SIGN NAGA TIMES SHU TENU;Lo;0;L;;;;;N;;;;;
+12243;CUNEIFORM SIGN NAGA OPPOSING NAGA;Lo;0;L;;;;;N;;;;;
+12244;CUNEIFORM SIGN NAGAR;Lo;0;L;;;;;N;;;;;
+12245;CUNEIFORM SIGN NAM NUTILLU;Lo;0;L;;;;;N;;;;;
+12246;CUNEIFORM SIGN NAM;Lo;0;L;;;;;N;;;;;
+12247;CUNEIFORM SIGN NAM2;Lo;0;L;;;;;N;;;;;
+12248;CUNEIFORM SIGN NE;Lo;0;L;;;;;N;;;;;
+12249;CUNEIFORM SIGN NE TIMES A;Lo;0;L;;;;;N;;;;;
+1224A;CUNEIFORM SIGN NE TIMES UD;Lo;0;L;;;;;N;;;;;
+1224B;CUNEIFORM SIGN NE SHESHIG;Lo;0;L;;;;;N;;;;;
+1224C;CUNEIFORM SIGN NI;Lo;0;L;;;;;N;;;;;
+1224D;CUNEIFORM SIGN NI TIMES E;Lo;0;L;;;;;N;;;;;
+1224E;CUNEIFORM SIGN NI2;Lo;0;L;;;;;N;;;;;
+1224F;CUNEIFORM SIGN NIM;Lo;0;L;;;;;N;;;;;
+12250;CUNEIFORM SIGN NIM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+12251;CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;;
+12252;CUNEIFORM SIGN NINDA2;Lo;0;L;;;;;N;;;;;
+12253;CUNEIFORM SIGN NINDA2 TIMES AN;Lo;0;L;;;;;N;;;;;
+12254;CUNEIFORM SIGN NINDA2 TIMES ASH;Lo;0;L;;;;;N;;;;;
+12255;CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH;Lo;0;L;;;;;N;;;;;
+12256;CUNEIFORM SIGN NINDA2 TIMES GUD;Lo;0;L;;;;;N;;;;;
+12257;CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;;
+12258;CUNEIFORM SIGN NINDA2 TIMES NE;Lo;0;L;;;;;N;;;;;
+12259;CUNEIFORM SIGN NINDA2 TIMES NUN;Lo;0;L;;;;;N;;;;;
+1225A;CUNEIFORM SIGN NINDA2 TIMES SHE;Lo;0;L;;;;;N;;;;;
+1225B;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN;Lo;0;L;;;;;N;;;;;
+1225C;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH;Lo;0;L;;;;;N;;;;;
+1225D;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH;Lo;0;L;;;;;N;;;;;
+1225E;CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;;
+1225F;CUNEIFORM SIGN NINDA2 TIMES USH;Lo;0;L;;;;;N;;;;;
+12260;CUNEIFORM SIGN NISAG;Lo;0;L;;;;;N;;;;;
+12261;CUNEIFORM SIGN NU;Lo;0;L;;;;;N;;;;;
+12262;CUNEIFORM SIGN NU11;Lo;0;L;;;;;N;;;;;
+12263;CUNEIFORM SIGN NUN;Lo;0;L;;;;;N;;;;;
+12264;CUNEIFORM SIGN NUN LAGAR TIMES GAR;Lo;0;L;;;;;N;;;;;
+12265;CUNEIFORM SIGN NUN LAGAR TIMES MASH;Lo;0;L;;;;;N;;;;;
+12266;CUNEIFORM SIGN NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;;
+12267;CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;;
+12268;CUNEIFORM SIGN NUN LAGAR TIMES USH;Lo;0;L;;;;;N;;;;;
+12269;CUNEIFORM SIGN NUN TENU;Lo;0;L;;;;;N;;;;;
+1226A;CUNEIFORM SIGN NUN OVER NUN;Lo;0;L;;;;;N;;;;;
+1226B;CUNEIFORM SIGN NUN CROSSING NUN;Lo;0;L;;;;;N;;;;;
+1226C;CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR;Lo;0;L;;;;;N;;;;;
+1226D;CUNEIFORM SIGN NUNUZ;Lo;0;L;;;;;N;;;;;
+1226E;CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB;Lo;0;L;;;;;N;;;;;
+1226F;CUNEIFORM SIGN NUNUZ AB2 TIMES BI;Lo;0;L;;;;;N;;;;;
+12270;CUNEIFORM SIGN NUNUZ AB2 TIMES DUG;Lo;0;L;;;;;N;;;;;
+12271;CUNEIFORM SIGN NUNUZ AB2 TIMES GUD;Lo;0;L;;;;;N;;;;;
+12272;CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+12273;CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3;Lo;0;L;;;;;N;;;;;
+12274;CUNEIFORM SIGN NUNUZ AB2 TIMES LA;Lo;0;L;;;;;N;;;;;
+12275;CUNEIFORM SIGN NUNUZ AB2 TIMES NE;Lo;0;L;;;;;N;;;;;
+12276;CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3;Lo;0;L;;;;;N;;;;;
+12277;CUNEIFORM SIGN NUNUZ AB2 TIMES U2;Lo;0;L;;;;;N;;;;;
+12278;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;;
+12279;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U;Lo;0;L;;;;;N;;;;;
+1227A;CUNEIFORM SIGN PA;Lo;0;L;;;;;N;;;;;
+1227B;CUNEIFORM SIGN PAD;Lo;0;L;;;;;N;;;;;
+1227C;CUNEIFORM SIGN PAN;Lo;0;L;;;;;N;;;;;
+1227D;CUNEIFORM SIGN PAP;Lo;0;L;;;;;N;;;;;
+1227E;CUNEIFORM SIGN PESH2;Lo;0;L;;;;;N;;;;;
+1227F;CUNEIFORM SIGN PI;Lo;0;L;;;;;N;;;;;
+12280;CUNEIFORM SIGN PI TIMES A;Lo;0;L;;;;;N;;;;;
+12281;CUNEIFORM SIGN PI TIMES AB;Lo;0;L;;;;;N;;;;;
+12282;CUNEIFORM SIGN PI TIMES BI;Lo;0;L;;;;;N;;;;;
+12283;CUNEIFORM SIGN PI TIMES BU;Lo;0;L;;;;;N;;;;;
+12284;CUNEIFORM SIGN PI TIMES E;Lo;0;L;;;;;N;;;;;
+12285;CUNEIFORM SIGN PI TIMES I;Lo;0;L;;;;;N;;;;;
+12286;CUNEIFORM SIGN PI TIMES IB;Lo;0;L;;;;;N;;;;;
+12287;CUNEIFORM SIGN PI TIMES U;Lo;0;L;;;;;N;;;;;
+12288;CUNEIFORM SIGN PI TIMES U2;Lo;0;L;;;;;N;;;;;
+12289;CUNEIFORM SIGN PI CROSSING PI;Lo;0;L;;;;;N;;;;;
+1228A;CUNEIFORM SIGN PIRIG;Lo;0;L;;;;;N;;;;;
+1228B;CUNEIFORM SIGN PIRIG TIMES KAL;Lo;0;L;;;;;N;;;;;
+1228C;CUNEIFORM SIGN PIRIG TIMES UD;Lo;0;L;;;;;N;;;;;
+1228D;CUNEIFORM SIGN PIRIG TIMES ZA;Lo;0;L;;;;;N;;;;;
+1228E;CUNEIFORM SIGN PIRIG OPPOSING PIRIG;Lo;0;L;;;;;N;;;;;
+1228F;CUNEIFORM SIGN RA;Lo;0;L;;;;;N;;;;;
+12290;CUNEIFORM SIGN RAB;Lo;0;L;;;;;N;;;;;
+12291;CUNEIFORM SIGN RI;Lo;0;L;;;;;N;;;;;
+12292;CUNEIFORM SIGN RU;Lo;0;L;;;;;N;;;;;
+12293;CUNEIFORM SIGN SA;Lo;0;L;;;;;N;;;;;
+12294;CUNEIFORM SIGN SAG NUTILLU;Lo;0;L;;;;;N;;;;;
+12295;CUNEIFORM SIGN SAG;Lo;0;L;;;;;N;;;;;
+12296;CUNEIFORM SIGN SAG TIMES A;Lo;0;L;;;;;N;;;;;
+12297;CUNEIFORM SIGN SAG TIMES DU;Lo;0;L;;;;;N;;;;;
+12298;CUNEIFORM SIGN SAG TIMES DUB;Lo;0;L;;;;;N;;;;;
+12299;CUNEIFORM SIGN SAG TIMES HA;Lo;0;L;;;;;N;;;;;
+1229A;CUNEIFORM SIGN SAG TIMES KAK;Lo;0;L;;;;;N;;;;;
+1229B;CUNEIFORM SIGN SAG TIMES KUR;Lo;0;L;;;;;N;;;;;
+1229C;CUNEIFORM SIGN SAG TIMES LUM;Lo;0;L;;;;;N;;;;;
+1229D;CUNEIFORM SIGN SAG TIMES MI;Lo;0;L;;;;;N;;;;;
+1229E;CUNEIFORM SIGN SAG TIMES NUN;Lo;0;L;;;;;N;;;;;
+1229F;CUNEIFORM SIGN SAG TIMES SAL;Lo;0;L;;;;;N;;;;;
+122A0;CUNEIFORM SIGN SAG TIMES SHID;Lo;0;L;;;;;N;;;;;
+122A1;CUNEIFORM SIGN SAG TIMES TAB;Lo;0;L;;;;;N;;;;;
+122A2;CUNEIFORM SIGN SAG TIMES U2;Lo;0;L;;;;;N;;;;;
+122A3;CUNEIFORM SIGN SAG TIMES UB;Lo;0;L;;;;;N;;;;;
+122A4;CUNEIFORM SIGN SAG TIMES UM;Lo;0;L;;;;;N;;;;;
+122A5;CUNEIFORM SIGN SAG TIMES UR;Lo;0;L;;;;;N;;;;;
+122A6;CUNEIFORM SIGN SAG TIMES USH;Lo;0;L;;;;;N;;;;;
+122A7;CUNEIFORM SIGN SAG OVER SAG;Lo;0;L;;;;;N;;;;;
+122A8;CUNEIFORM SIGN SAG GUNU;Lo;0;L;;;;;N;;;;;
+122A9;CUNEIFORM SIGN SAL;Lo;0;L;;;;;N;;;;;
+122AA;CUNEIFORM SIGN SAL LAGAB TIMES ASH2;Lo;0;L;;;;;N;;;;;
+122AB;CUNEIFORM SIGN SANGA2;Lo;0;L;;;;;N;;;;;
+122AC;CUNEIFORM SIGN SAR;Lo;0;L;;;;;N;;;;;
+122AD;CUNEIFORM SIGN SHA;Lo;0;L;;;;;N;;;;;
+122AE;CUNEIFORM SIGN SHA3;Lo;0;L;;;;;N;;;;;
+122AF;CUNEIFORM SIGN SHA3 TIMES A;Lo;0;L;;;;;N;;;;;
+122B0;CUNEIFORM SIGN SHA3 TIMES BAD;Lo;0;L;;;;;N;;;;;
+122B1;CUNEIFORM SIGN SHA3 TIMES GISH;Lo;0;L;;;;;N;;;;;
+122B2;CUNEIFORM SIGN SHA3 TIMES NE;Lo;0;L;;;;;N;;;;;
+122B3;CUNEIFORM SIGN SHA3 TIMES SHU2;Lo;0;L;;;;;N;;;;;
+122B4;CUNEIFORM SIGN SHA3 TIMES TUR;Lo;0;L;;;;;N;;;;;
+122B5;CUNEIFORM SIGN SHA3 TIMES U;Lo;0;L;;;;;N;;;;;
+122B6;CUNEIFORM SIGN SHA3 TIMES U PLUS A;Lo;0;L;;;;;N;;;;;
+122B7;CUNEIFORM SIGN SHA6;Lo;0;L;;;;;N;;;;;
+122B8;CUNEIFORM SIGN SHAB6;Lo;0;L;;;;;N;;;;;
+122B9;CUNEIFORM SIGN SHAR2;Lo;0;L;;;;;N;;;;;
+122BA;CUNEIFORM SIGN SHE;Lo;0;L;;;;;N;;;;;
+122BB;CUNEIFORM SIGN SHE HU;Lo;0;L;;;;;N;;;;;
+122BC;CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
+122BD;CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR;Lo;0;L;;;;;N;;;;;
+122BE;CUNEIFORM SIGN SHEG9;Lo;0;L;;;;;N;;;;;
+122BF;CUNEIFORM SIGN SHEN;Lo;0;L;;;;;N;;;;;
+122C0;CUNEIFORM SIGN SHESH;Lo;0;L;;;;;N;;;;;
+122C1;CUNEIFORM SIGN SHESH2;Lo;0;L;;;;;N;;;;;
+122C2;CUNEIFORM SIGN SHESHLAM;Lo;0;L;;;;;N;;;;;
+122C3;CUNEIFORM SIGN SHID;Lo;0;L;;;;;N;;;;;
+122C4;CUNEIFORM SIGN SHID TIMES A;Lo;0;L;;;;;N;;;;;
+122C5;CUNEIFORM SIGN SHID TIMES IM;Lo;0;L;;;;;N;;;;;
+122C6;CUNEIFORM SIGN SHIM;Lo;0;L;;;;;N;;;;;
+122C7;CUNEIFORM SIGN SHIM TIMES A;Lo;0;L;;;;;N;;;;;
+122C8;CUNEIFORM SIGN SHIM TIMES BAL;Lo;0;L;;;;;N;;;;;
+122C9;CUNEIFORM SIGN SHIM TIMES BULUG;Lo;0;L;;;;;N;;;;;
+122CA;CUNEIFORM SIGN SHIM TIMES DIN;Lo;0;L;;;;;N;;;;;
+122CB;CUNEIFORM SIGN SHIM TIMES GAR;Lo;0;L;;;;;N;;;;;
+122CC;CUNEIFORM SIGN SHIM TIMES IGI;Lo;0;L;;;;;N;;;;;
+122CD;CUNEIFORM SIGN SHIM TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+122CE;CUNEIFORM SIGN SHIM TIMES KUSHU2;Lo;0;L;;;;;N;;;;;
+122CF;CUNEIFORM SIGN SHIM TIMES LUL;Lo;0;L;;;;;N;;;;;
+122D0;CUNEIFORM SIGN SHIM TIMES MUG;Lo;0;L;;;;;N;;;;;
+122D1;CUNEIFORM SIGN SHIM TIMES SAL;Lo;0;L;;;;;N;;;;;
+122D2;CUNEIFORM SIGN SHINIG;Lo;0;L;;;;;N;;;;;
+122D3;CUNEIFORM SIGN SHIR;Lo;0;L;;;;;N;;;;;
+122D4;CUNEIFORM SIGN SHIR TENU;Lo;0;L;;;;;N;;;;;
+122D5;CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR;Lo;0;L;;;;;N;;;;;
+122D6;CUNEIFORM SIGN SHITA;Lo;0;L;;;;;N;;;;;
+122D7;CUNEIFORM SIGN SHU;Lo;0;L;;;;;N;;;;;
+122D8;CUNEIFORM SIGN SHU OVER INVERTED SHU;Lo;0;L;;;;;N;;;;;
+122D9;CUNEIFORM SIGN SHU2;Lo;0;L;;;;;N;;;;;
+122DA;CUNEIFORM SIGN SHUBUR;Lo;0;L;;;;;N;;;;;
+122DB;CUNEIFORM SIGN SI;Lo;0;L;;;;;N;;;;;
+122DC;CUNEIFORM SIGN SI GUNU;Lo;0;L;;;;;N;;;;;
+122DD;CUNEIFORM SIGN SIG;Lo;0;L;;;;;N;;;;;
+122DE;CUNEIFORM SIGN SIG4;Lo;0;L;;;;;N;;;;;
+122DF;CUNEIFORM SIGN SIG4 OVER SIG4 SHU2;Lo;0;L;;;;;N;;;;;
+122E0;CUNEIFORM SIGN SIK2;Lo;0;L;;;;;N;;;;;
+122E1;CUNEIFORM SIGN SILA3;Lo;0;L;;;;;N;;;;;
+122E2;CUNEIFORM SIGN SU;Lo;0;L;;;;;N;;;;;
+122E3;CUNEIFORM SIGN SU OVER SU;Lo;0;L;;;;;N;;;;;
+122E4;CUNEIFORM SIGN SUD;Lo;0;L;;;;;N;;;;;
+122E5;CUNEIFORM SIGN SUD2;Lo;0;L;;;;;N;;;;;
+122E6;CUNEIFORM SIGN SUHUR;Lo;0;L;;;;;N;;;;;
+122E7;CUNEIFORM SIGN SUM;Lo;0;L;;;;;N;;;;;
+122E8;CUNEIFORM SIGN SUMASH;Lo;0;L;;;;;N;;;;;
+122E9;CUNEIFORM SIGN SUR;Lo;0;L;;;;;N;;;;;
+122EA;CUNEIFORM SIGN SUR9;Lo;0;L;;;;;N;;;;;
+122EB;CUNEIFORM SIGN TA;Lo;0;L;;;;;N;;;;;
+122EC;CUNEIFORM SIGN TA ASTERISK;Lo;0;L;;;;;N;;;;;
+122ED;CUNEIFORM SIGN TA TIMES HI;Lo;0;L;;;;;N;;;;;
+122EE;CUNEIFORM SIGN TA TIMES MI;Lo;0;L;;;;;N;;;;;
+122EF;CUNEIFORM SIGN TA GUNU;Lo;0;L;;;;;N;;;;;
+122F0;CUNEIFORM SIGN TAB;Lo;0;L;;;;;N;;;;;
+122F1;CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH;Lo;0;L;;;;;N;;;;;
+122F2;CUNEIFORM SIGN TAB SQUARED;Lo;0;L;;;;;N;;;;;
+122F3;CUNEIFORM SIGN TAG;Lo;0;L;;;;;N;;;;;
+122F4;CUNEIFORM SIGN TAG TIMES BI;Lo;0;L;;;;;N;;;;;
+122F5;CUNEIFORM SIGN TAG TIMES GUD;Lo;0;L;;;;;N;;;;;
+122F6;CUNEIFORM SIGN TAG TIMES SHE;Lo;0;L;;;;;N;;;;;
+122F7;CUNEIFORM SIGN TAG TIMES SHU;Lo;0;L;;;;;N;;;;;
+122F8;CUNEIFORM SIGN TAG TIMES TUG2;Lo;0;L;;;;;N;;;;;
+122F9;CUNEIFORM SIGN TAG TIMES UD;Lo;0;L;;;;;N;;;;;
+122FA;CUNEIFORM SIGN TAK4;Lo;0;L;;;;;N;;;;;
+122FB;CUNEIFORM SIGN TAR;Lo;0;L;;;;;N;;;;;
+122FC;CUNEIFORM SIGN TE;Lo;0;L;;;;;N;;;;;
+122FD;CUNEIFORM SIGN TE GUNU;Lo;0;L;;;;;N;;;;;
+122FE;CUNEIFORM SIGN TI;Lo;0;L;;;;;N;;;;;
+122FF;CUNEIFORM SIGN TI TENU;Lo;0;L;;;;;N;;;;;
+12300;CUNEIFORM SIGN TIL;Lo;0;L;;;;;N;;;;;
+12301;CUNEIFORM SIGN TIR;Lo;0;L;;;;;N;;;;;
+12302;CUNEIFORM SIGN TIR TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12303;CUNEIFORM SIGN TIR OVER TIR;Lo;0;L;;;;;N;;;;;
+12304;CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;;
+12305;CUNEIFORM SIGN TU;Lo;0;L;;;;;N;;;;;
+12306;CUNEIFORM SIGN TUG2;Lo;0;L;;;;;N;;;;;
+12307;CUNEIFORM SIGN TUK;Lo;0;L;;;;;N;;;;;
+12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;;
+12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;;
+1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;;
+1230B;CUNEIFORM SIGN U;Lo;0;L;;;;;N;;;;;
+1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;;
+1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;;N;;;;;
+1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;;
+1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;;
+12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;;
+12311;CUNEIFORM SIGN U2;Lo;0;L;;;;;N;;;;;
+12312;CUNEIFORM SIGN UB;Lo;0;L;;;;;N;;;;;
+12313;CUNEIFORM SIGN UD;Lo;0;L;;;;;N;;;;;
+12314;CUNEIFORM SIGN UD KUSHU2;Lo;0;L;;;;;N;;;;;
+12315;CUNEIFORM SIGN UD TIMES BAD;Lo;0;L;;;;;N;;;;;
+12316;CUNEIFORM SIGN UD TIMES MI;Lo;0;L;;;;;N;;;;;
+12317;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;;
+12318;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU;Lo;0;L;;;;;N;;;;;
+12319;CUNEIFORM SIGN UD GUNU;Lo;0;L;;;;;N;;;;;
+1231A;CUNEIFORM SIGN UD SHESHIG;Lo;0;L;;;;;N;;;;;
+1231B;CUNEIFORM SIGN UD SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;;
+1231C;CUNEIFORM SIGN UDUG;Lo;0;L;;;;;N;;;;;
+1231D;CUNEIFORM SIGN UM;Lo;0;L;;;;;N;;;;;
+1231E;CUNEIFORM SIGN UM TIMES LAGAB;Lo;0;L;;;;;N;;;;;
+1231F;CUNEIFORM SIGN UM TIMES ME PLUS DA;Lo;0;L;;;;;N;;;;;
+12320;CUNEIFORM SIGN UM TIMES SHA3;Lo;0;L;;;;;N;;;;;
+12321;CUNEIFORM SIGN UM TIMES U;Lo;0;L;;;;;N;;;;;
+12322;CUNEIFORM SIGN UMBIN;Lo;0;L;;;;;N;;;;;
+12323;CUNEIFORM SIGN UMUM;Lo;0;L;;;;;N;;;;;
+12324;CUNEIFORM SIGN UMUM TIMES KASKAL;Lo;0;L;;;;;N;;;;;
+12325;CUNEIFORM SIGN UMUM TIMES PA;Lo;0;L;;;;;N;;;;;
+12326;CUNEIFORM SIGN UN;Lo;0;L;;;;;N;;;;;
+12327;CUNEIFORM SIGN UN GUNU;Lo;0;L;;;;;N;;;;;
+12328;CUNEIFORM SIGN UR;Lo;0;L;;;;;N;;;;;
+12329;CUNEIFORM SIGN UR CROSSING UR;Lo;0;L;;;;;N;;;;;
+1232A;CUNEIFORM SIGN UR SHESHIG;Lo;0;L;;;;;N;;;;;
+1232B;CUNEIFORM SIGN UR2;Lo;0;L;;;;;N;;;;;
+1232C;CUNEIFORM SIGN UR2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;;
+1232D;CUNEIFORM SIGN UR2 TIMES A PLUS NA;Lo;0;L;;;;;N;;;;;
+1232E;CUNEIFORM SIGN UR2 TIMES AL;Lo;0;L;;;;;N;;;;;
+1232F;CUNEIFORM SIGN UR2 TIMES HA;Lo;0;L;;;;;N;;;;;
+12330;CUNEIFORM SIGN UR2 TIMES NUN;Lo;0;L;;;;;N;;;;;
+12331;CUNEIFORM SIGN UR2 TIMES U2;Lo;0;L;;;;;N;;;;;
+12332;CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;;
+12333;CUNEIFORM SIGN UR2 TIMES U2 PLUS BI;Lo;0;L;;;;;N;;;;;
+12334;CUNEIFORM SIGN UR4;Lo;0;L;;;;;N;;;;;
+12335;CUNEIFORM SIGN URI;Lo;0;L;;;;;N;;;;;
+12336;CUNEIFORM SIGN URI3;Lo;0;L;;;;;N;;;;;
+12337;CUNEIFORM SIGN URU;Lo;0;L;;;;;N;;;;;
+12338;CUNEIFORM SIGN URU TIMES A;Lo;0;L;;;;;N;;;;;
+12339;CUNEIFORM SIGN URU TIMES ASHGAB;Lo;0;L;;;;;N;;;;;
+1233A;CUNEIFORM SIGN URU TIMES BAR;Lo;0;L;;;;;N;;;;;
+1233B;CUNEIFORM SIGN URU TIMES DUN;Lo;0;L;;;;;N;;;;;
+1233C;CUNEIFORM SIGN URU TIMES GA;Lo;0;L;;;;;N;;;;;
+1233D;CUNEIFORM SIGN URU TIMES GAL;Lo;0;L;;;;;N;;;;;
+1233E;CUNEIFORM SIGN URU TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+1233F;CUNEIFORM SIGN URU TIMES GAR;Lo;0;L;;;;;N;;;;;
+12340;CUNEIFORM SIGN URU TIMES GU;Lo;0;L;;;;;N;;;;;
+12341;CUNEIFORM SIGN URU TIMES HA;Lo;0;L;;;;;N;;;;;
+12342;CUNEIFORM SIGN URU TIMES IGI;Lo;0;L;;;;;N;;;;;
+12343;CUNEIFORM SIGN URU TIMES IM;Lo;0;L;;;;;N;;;;;
+12344;CUNEIFORM SIGN URU TIMES ISH;Lo;0;L;;;;;N;;;;;
+12345;CUNEIFORM SIGN URU TIMES KI;Lo;0;L;;;;;N;;;;;
+12346;CUNEIFORM SIGN URU TIMES LUM;Lo;0;L;;;;;N;;;;;
+12347;CUNEIFORM SIGN URU TIMES MIN;Lo;0;L;;;;;N;;;;;
+12348;CUNEIFORM SIGN URU TIMES PA;Lo;0;L;;;;;N;;;;;
+12349;CUNEIFORM SIGN URU TIMES SHE;Lo;0;L;;;;;N;;;;;
+1234A;CUNEIFORM SIGN URU TIMES SIG4;Lo;0;L;;;;;N;;;;;
+1234B;CUNEIFORM SIGN URU TIMES TU;Lo;0;L;;;;;N;;;;;
+1234C;CUNEIFORM SIGN URU TIMES U PLUS GUD;Lo;0;L;;;;;N;;;;;
+1234D;CUNEIFORM SIGN URU TIMES UD;Lo;0;L;;;;;N;;;;;
+1234E;CUNEIFORM SIGN URU TIMES URUDA;Lo;0;L;;;;;N;;;;;
+1234F;CUNEIFORM SIGN URUDA;Lo;0;L;;;;;N;;;;;
+12350;CUNEIFORM SIGN URUDA TIMES U;Lo;0;L;;;;;N;;;;;
+12351;CUNEIFORM SIGN USH;Lo;0;L;;;;;N;;;;;
+12352;CUNEIFORM SIGN USH TIMES A;Lo;0;L;;;;;N;;;;;
+12353;CUNEIFORM SIGN USH TIMES KU;Lo;0;L;;;;;N;;;;;
+12354;CUNEIFORM SIGN USH TIMES KUR;Lo;0;L;;;;;N;;;;;
+12355;CUNEIFORM SIGN USH TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12356;CUNEIFORM SIGN USHX;Lo;0;L;;;;;N;;;;;
+12357;CUNEIFORM SIGN USH2;Lo;0;L;;;;;N;;;;;
+12358;CUNEIFORM SIGN USHUMX;Lo;0;L;;;;;N;;;;;
+12359;CUNEIFORM SIGN UTUKI;Lo;0;L;;;;;N;;;;;
+1235A;CUNEIFORM SIGN UZ3;Lo;0;L;;;;;N;;;;;
+1235B;CUNEIFORM SIGN UZ3 TIMES KASKAL;Lo;0;L;;;;;N;;;;;
+1235C;CUNEIFORM SIGN UZU;Lo;0;L;;;;;N;;;;;
+1235D;CUNEIFORM SIGN ZA;Lo;0;L;;;;;N;;;;;
+1235E;CUNEIFORM SIGN ZA TENU;Lo;0;L;;;;;N;;;;;
+1235F;CUNEIFORM SIGN ZA SQUARED TIMES KUR;Lo;0;L;;;;;N;;;;;
+12360;CUNEIFORM SIGN ZAG;Lo;0;L;;;;;N;;;;;
+12361;CUNEIFORM SIGN ZAMX;Lo;0;L;;;;;N;;;;;
+12362;CUNEIFORM SIGN ZE2;Lo;0;L;;;;;N;;;;;
+12363;CUNEIFORM SIGN ZI;Lo;0;L;;;;;N;;;;;
+12364;CUNEIFORM SIGN ZI OVER ZI;Lo;0;L;;;;;N;;;;;
+12365;CUNEIFORM SIGN ZI3;Lo;0;L;;;;;N;;;;;
+12366;CUNEIFORM SIGN ZIB;Lo;0;L;;;;;N;;;;;
+12367;CUNEIFORM SIGN ZIB KABA TENU;Lo;0;L;;;;;N;;;;;
+12368;CUNEIFORM SIGN ZIG;Lo;0;L;;;;;N;;;;;
+12369;CUNEIFORM SIGN ZIZ2;Lo;0;L;;;;;N;;;;;
+1236A;CUNEIFORM SIGN ZU;Lo;0;L;;;;;N;;;;;
+1236B;CUNEIFORM SIGN ZU5;Lo;0;L;;;;;N;;;;;
+1236C;CUNEIFORM SIGN ZU5 TIMES A;Lo;0;L;;;;;N;;;;;
+1236D;CUNEIFORM SIGN ZUBUR;Lo;0;L;;;;;N;;;;;
+1236E;CUNEIFORM SIGN ZUM;Lo;0;L;;;;;N;;;;;
+12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;;
+12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;;
+12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;;
+12403;CUNEIFORM NUMERIC SIGN FIVE ASH;Nl;0;L;;;;5;N;;;;;
+12404;CUNEIFORM NUMERIC SIGN SIX ASH;Nl;0;L;;;;6;N;;;;;
+12405;CUNEIFORM NUMERIC SIGN SEVEN ASH;Nl;0;L;;;;7;N;;;;;
+12406;CUNEIFORM NUMERIC SIGN EIGHT ASH;Nl;0;L;;;;8;N;;;;;
+12407;CUNEIFORM NUMERIC SIGN NINE ASH;Nl;0;L;;;;9;N;;;;;
+12408;CUNEIFORM NUMERIC SIGN THREE DISH;Nl;0;L;;;;3;N;;;;;
+12409;CUNEIFORM NUMERIC SIGN FOUR DISH;Nl;0;L;;;;4;N;;;;;
+1240A;CUNEIFORM NUMERIC SIGN FIVE DISH;Nl;0;L;;;;5;N;;;;;
+1240B;CUNEIFORM NUMERIC SIGN SIX DISH;Nl;0;L;;;;6;N;;;;;
+1240C;CUNEIFORM NUMERIC SIGN SEVEN DISH;Nl;0;L;;;;7;N;;;;;
+1240D;CUNEIFORM NUMERIC SIGN EIGHT DISH;Nl;0;L;;;;8;N;;;;;
+1240E;CUNEIFORM NUMERIC SIGN NINE DISH;Nl;0;L;;;;9;N;;;;;
+1240F;CUNEIFORM NUMERIC SIGN FOUR U;Nl;0;L;;;;4;N;;;;;
+12410;CUNEIFORM NUMERIC SIGN FIVE U;Nl;0;L;;;;5;N;;;;;
+12411;CUNEIFORM NUMERIC SIGN SIX U;Nl;0;L;;;;6;N;;;;;
+12412;CUNEIFORM NUMERIC SIGN SEVEN U;Nl;0;L;;;;7;N;;;;;
+12413;CUNEIFORM NUMERIC SIGN EIGHT U;Nl;0;L;;;;8;N;;;;;
+12414;CUNEIFORM NUMERIC SIGN NINE U;Nl;0;L;;;;9;N;;;;;
+12415;CUNEIFORM NUMERIC SIGN ONE GESH2;Nl;0;L;;;;1;N;;;;;
+12416;CUNEIFORM NUMERIC SIGN TWO GESH2;Nl;0;L;;;;2;N;;;;;
+12417;CUNEIFORM NUMERIC SIGN THREE GESH2;Nl;0;L;;;;3;N;;;;;
+12418;CUNEIFORM NUMERIC SIGN FOUR GESH2;Nl;0;L;;;;4;N;;;;;
+12419;CUNEIFORM NUMERIC SIGN FIVE GESH2;Nl;0;L;;;;5;N;;;;;
+1241A;CUNEIFORM NUMERIC SIGN SIX GESH2;Nl;0;L;;;;6;N;;;;;
+1241B;CUNEIFORM NUMERIC SIGN SEVEN GESH2;Nl;0;L;;;;7;N;;;;;
+1241C;CUNEIFORM NUMERIC SIGN EIGHT GESH2;Nl;0;L;;;;8;N;;;;;
+1241D;CUNEIFORM NUMERIC SIGN NINE GESH2;Nl;0;L;;;;9;N;;;;;
+1241E;CUNEIFORM NUMERIC SIGN ONE GESHU;Nl;0;L;;;;1;N;;;;;
+1241F;CUNEIFORM NUMERIC SIGN TWO GESHU;Nl;0;L;;;;2;N;;;;;
+12420;CUNEIFORM NUMERIC SIGN THREE GESHU;Nl;0;L;;;;3;N;;;;;
+12421;CUNEIFORM NUMERIC SIGN FOUR GESHU;Nl;0;L;;;;4;N;;;;;
+12422;CUNEIFORM NUMERIC SIGN FIVE GESHU;Nl;0;L;;;;5;N;;;;;
+12423;CUNEIFORM NUMERIC SIGN TWO SHAR2;Nl;0;L;;;;2;N;;;;;
+12424;CUNEIFORM NUMERIC SIGN THREE SHAR2;Nl;0;L;;;;3;N;;;;;
+12425;CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM;Nl;0;L;;;;3;N;;;;;
+12426;CUNEIFORM NUMERIC SIGN FOUR SHAR2;Nl;0;L;;;;4;N;;;;;
+12427;CUNEIFORM NUMERIC SIGN FIVE SHAR2;Nl;0;L;;;;5;N;;;;;
+12428;CUNEIFORM NUMERIC SIGN SIX SHAR2;Nl;0;L;;;;6;N;;;;;
+12429;CUNEIFORM NUMERIC SIGN SEVEN SHAR2;Nl;0;L;;;;7;N;;;;;
+1242A;CUNEIFORM NUMERIC SIGN EIGHT SHAR2;Nl;0;L;;;;8;N;;;;;
+1242B;CUNEIFORM NUMERIC SIGN NINE SHAR2;Nl;0;L;;;;9;N;;;;;
+1242C;CUNEIFORM NUMERIC SIGN ONE SHARU;Nl;0;L;;;;1;N;;;;;
+1242D;CUNEIFORM NUMERIC SIGN TWO SHARU;Nl;0;L;;;;2;N;;;;;
+1242E;CUNEIFORM NUMERIC SIGN THREE SHARU;Nl;0;L;;;;3;N;;;;;
+1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;;
+12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;;
+12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;;
+12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;;N;;;;;
+12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;;N;;;;;
+12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;;
+12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;;
+12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;;
+12437;CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM;Nl;0;L;;;;3;N;;;;;
+12438;CUNEIFORM NUMERIC SIGN FOUR BURU;Nl;0;L;;;;4;N;;;;;
+12439;CUNEIFORM NUMERIC SIGN FIVE BURU;Nl;0;L;;;;5;N;;;;;
+1243A;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16;Nl;0;L;;;;3;N;;;;;
+1243B;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21;Nl;0;L;;;;3;N;;;;;
+1243C;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU;Nl;0;L;;;;4;N;;;;;
+1243D;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4;Nl;0;L;;;;4;N;;;;;
+1243E;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A;Nl;0;L;;;;4;N;;;;;
+1243F;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B;Nl;0;L;;;;4;N;;;;;
+12440;CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9;Nl;0;L;;;;6;N;;;;;
+12441;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3;Nl;0;L;;;;7;N;;;;;
+12442;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A;Nl;0;L;;;;7;N;;;;;
+12443;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B;Nl;0;L;;;;7;N;;;;;
+12444;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU;Nl;0;L;;;;8;N;;;;;
+12445;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3;Nl;0;L;;;;8;N;;;;;
+12446;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU;Nl;0;L;;;;9;N;;;;;
+12447;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3;Nl;0;L;;;;9;N;;;;;
+12448;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4;Nl;0;L;;;;9;N;;;;;
+12449;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A;Nl;0;L;;;;9;N;;;;;
+1244A;CUNEIFORM NUMERIC SIGN TWO ASH TENU;Nl;0;L;;;;2;N;;;;;
+1244B;CUNEIFORM NUMERIC SIGN THREE ASH TENU;Nl;0;L;;;;3;N;;;;;
+1244C;CUNEIFORM NUMERIC SIGN FOUR ASH TENU;Nl;0;L;;;;4;N;;;;;
+1244D;CUNEIFORM NUMERIC SIGN FIVE ASH TENU;Nl;0;L;;;;5;N;;;;;
+1244E;CUNEIFORM NUMERIC SIGN SIX ASH TENU;Nl;0;L;;;;6;N;;;;;
+1244F;CUNEIFORM NUMERIC SIGN ONE BAN2;Nl;0;L;;;;1;N;;;;;
+12450;CUNEIFORM NUMERIC SIGN TWO BAN2;Nl;0;L;;;;2;N;;;;;
+12451;CUNEIFORM NUMERIC SIGN THREE BAN2;Nl;0;L;;;;3;N;;;;;
+12452;CUNEIFORM NUMERIC SIGN FOUR BAN2;Nl;0;L;;;;4;N;;;;;
+12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;;
+12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;;
+12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;;
+12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;;N;;;;;
+12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;;N;;;;;
+12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;;
+12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;;
+1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;;
+1245B;CUNEIFORM NUMERIC SIGN TWO THIRDS DISH;Nl;0;L;;;;2/3;N;;;;;
+1245C;CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH;Nl;0;L;;;;5/6;N;;;;;
+1245D;CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A;Nl;0;L;;;;1/3;N;;;;;
+1245E;CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A;Nl;0;L;;;;2/3;N;;;;;
+1245F;CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH;Nl;0;L;;;;1/8;N;;;;;
+12460;CUNEIFORM NUMERIC SIGN ONE QUARTER ASH;Nl;0;L;;;;1/4;N;;;;;
+12461;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH;Nl;0;L;;;;1/6;N;;;;;
+12462;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER;Nl;0;L;;;;1/4;N;;;;;
+12470;CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER;Po;0;L;;;;;N;;;;;
+12471;CUNEIFORM PUNCTUATION SIGN VERTICAL COLON;Po;0;L;;;;;N;;;;;
+12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;;
+12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;;
+13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;;
+13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;;
+13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;;
+13003;EGYPTIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;;
+13004;EGYPTIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;;
+13005;EGYPTIAN HIEROGLYPH A005A;Lo;0;L;;;;;N;;;;;
+13006;EGYPTIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;;
+13007;EGYPTIAN HIEROGLYPH A006A;Lo;0;L;;;;;N;;;;;
+13008;EGYPTIAN HIEROGLYPH A006B;Lo;0;L;;;;;N;;;;;
+13009;EGYPTIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;;
+1300A;EGYPTIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;;
+1300B;EGYPTIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;;
+1300C;EGYPTIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;;
+1300D;EGYPTIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;;
+1300E;EGYPTIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;;
+1300F;EGYPTIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;;
+13010;EGYPTIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;;
+13011;EGYPTIAN HIEROGLYPH A014A;Lo;0;L;;;;;N;;;;;
+13012;EGYPTIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;;
+13013;EGYPTIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;;
+13014;EGYPTIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;;
+13015;EGYPTIAN HIEROGLYPH A017A;Lo;0;L;;;;;N;;;;;
+13016;EGYPTIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;;
+13017;EGYPTIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;;
+13018;EGYPTIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;;
+13019;EGYPTIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;;
+1301A;EGYPTIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;;
+1301B;EGYPTIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;;
+1301C;EGYPTIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;;
+1301D;EGYPTIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;;
+1301E;EGYPTIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;;
+1301F;EGYPTIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;;
+13020;EGYPTIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;;
+13021;EGYPTIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;;
+13022;EGYPTIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;;
+13023;EGYPTIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;;
+13024;EGYPTIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;;
+13025;EGYPTIAN HIEROGLYPH A032A;Lo;0;L;;;;;N;;;;;
+13026;EGYPTIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;;
+13027;EGYPTIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;;
+13028;EGYPTIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;;
+13029;EGYPTIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;;
+1302A;EGYPTIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;;
+1302B;EGYPTIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;;
+1302C;EGYPTIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;;
+1302D;EGYPTIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;;
+1302E;EGYPTIAN HIEROGLYPH A040A;Lo;0;L;;;;;N;;;;;
+1302F;EGYPTIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;;
+13030;EGYPTIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;;
+13031;EGYPTIAN HIEROGLYPH A042A;Lo;0;L;;;;;N;;;;;
+13032;EGYPTIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;;
+13033;EGYPTIAN HIEROGLYPH A043A;Lo;0;L;;;;;N;;;;;
+13034;EGYPTIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;;
+13035;EGYPTIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;;
+13036;EGYPTIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;;
+13037;EGYPTIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;;
+13038;EGYPTIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;;
+13039;EGYPTIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;;
+1303A;EGYPTIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;;
+1303B;EGYPTIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;;
+1303C;EGYPTIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;;
+1303D;EGYPTIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;;
+1303E;EGYPTIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;;
+1303F;EGYPTIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;;
+13040;EGYPTIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;;
+13041;EGYPTIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;;
+13042;EGYPTIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;;
+13043;EGYPTIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;;
+13044;EGYPTIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;;
+13045;EGYPTIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;;
+13046;EGYPTIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;;
+13047;EGYPTIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;;
+13048;EGYPTIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;;
+13049;EGYPTIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;;
+1304A;EGYPTIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;;
+1304B;EGYPTIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;;
+1304C;EGYPTIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;;
+1304D;EGYPTIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;;
+1304E;EGYPTIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;;
+1304F;EGYPTIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;;
+13050;EGYPTIAN HIEROGLYPH B001;Lo;0;L;;;;;N;;;;;
+13051;EGYPTIAN HIEROGLYPH B002;Lo;0;L;;;;;N;;;;;
+13052;EGYPTIAN HIEROGLYPH B003;Lo;0;L;;;;;N;;;;;
+13053;EGYPTIAN HIEROGLYPH B004;Lo;0;L;;;;;N;;;;;
+13054;EGYPTIAN HIEROGLYPH B005;Lo;0;L;;;;;N;;;;;
+13055;EGYPTIAN HIEROGLYPH B005A;Lo;0;L;;;;;N;;;;;
+13056;EGYPTIAN HIEROGLYPH B006;Lo;0;L;;;;;N;;;;;
+13057;EGYPTIAN HIEROGLYPH B007;Lo;0;L;;;;;N;;;;;
+13058;EGYPTIAN HIEROGLYPH B008;Lo;0;L;;;;;N;;;;;
+13059;EGYPTIAN HIEROGLYPH B009;Lo;0;L;;;;;N;;;;;
+1305A;EGYPTIAN HIEROGLYPH C001;Lo;0;L;;;;;N;;;;;
+1305B;EGYPTIAN HIEROGLYPH C002;Lo;0;L;;;;;N;;;;;
+1305C;EGYPTIAN HIEROGLYPH C002A;Lo;0;L;;;;;N;;;;;
+1305D;EGYPTIAN HIEROGLYPH C002B;Lo;0;L;;;;;N;;;;;
+1305E;EGYPTIAN HIEROGLYPH C002C;Lo;0;L;;;;;N;;;;;
+1305F;EGYPTIAN HIEROGLYPH C003;Lo;0;L;;;;;N;;;;;
+13060;EGYPTIAN HIEROGLYPH C004;Lo;0;L;;;;;N;;;;;
+13061;EGYPTIAN HIEROGLYPH C005;Lo;0;L;;;;;N;;;;;
+13062;EGYPTIAN HIEROGLYPH C006;Lo;0;L;;;;;N;;;;;
+13063;EGYPTIAN HIEROGLYPH C007;Lo;0;L;;;;;N;;;;;
+13064;EGYPTIAN HIEROGLYPH C008;Lo;0;L;;;;;N;;;;;
+13065;EGYPTIAN HIEROGLYPH C009;Lo;0;L;;;;;N;;;;;
+13066;EGYPTIAN HIEROGLYPH C010;Lo;0;L;;;;;N;;;;;
+13067;EGYPTIAN HIEROGLYPH C010A;Lo;0;L;;;;;N;;;;;
+13068;EGYPTIAN HIEROGLYPH C011;Lo;0;L;;;;;N;;;;;
+13069;EGYPTIAN HIEROGLYPH C012;Lo;0;L;;;;;N;;;;;
+1306A;EGYPTIAN HIEROGLYPH C013;Lo;0;L;;;;;N;;;;;
+1306B;EGYPTIAN HIEROGLYPH C014;Lo;0;L;;;;;N;;;;;
+1306C;EGYPTIAN HIEROGLYPH C015;Lo;0;L;;;;;N;;;;;
+1306D;EGYPTIAN HIEROGLYPH C016;Lo;0;L;;;;;N;;;;;
+1306E;EGYPTIAN HIEROGLYPH C017;Lo;0;L;;;;;N;;;;;
+1306F;EGYPTIAN HIEROGLYPH C018;Lo;0;L;;;;;N;;;;;
+13070;EGYPTIAN HIEROGLYPH C019;Lo;0;L;;;;;N;;;;;
+13071;EGYPTIAN HIEROGLYPH C020;Lo;0;L;;;;;N;;;;;
+13072;EGYPTIAN HIEROGLYPH C021;Lo;0;L;;;;;N;;;;;
+13073;EGYPTIAN HIEROGLYPH C022;Lo;0;L;;;;;N;;;;;
+13074;EGYPTIAN HIEROGLYPH C023;Lo;0;L;;;;;N;;;;;
+13075;EGYPTIAN HIEROGLYPH C024;Lo;0;L;;;;;N;;;;;
+13076;EGYPTIAN HIEROGLYPH D001;Lo;0;L;;;;;N;;;;;
+13077;EGYPTIAN HIEROGLYPH D002;Lo;0;L;;;;;N;;;;;
+13078;EGYPTIAN HIEROGLYPH D003;Lo;0;L;;;;;N;;;;;
+13079;EGYPTIAN HIEROGLYPH D004;Lo;0;L;;;;;N;;;;;
+1307A;EGYPTIAN HIEROGLYPH D005;Lo;0;L;;;;;N;;;;;
+1307B;EGYPTIAN HIEROGLYPH D006;Lo;0;L;;;;;N;;;;;
+1307C;EGYPTIAN HIEROGLYPH D007;Lo;0;L;;;;;N;;;;;
+1307D;EGYPTIAN HIEROGLYPH D008;Lo;0;L;;;;;N;;;;;
+1307E;EGYPTIAN HIEROGLYPH D008A;Lo;0;L;;;;;N;;;;;
+1307F;EGYPTIAN HIEROGLYPH D009;Lo;0;L;;;;;N;;;;;
+13080;EGYPTIAN HIEROGLYPH D010;Lo;0;L;;;;;N;;;;;
+13081;EGYPTIAN HIEROGLYPH D011;Lo;0;L;;;;;N;;;;;
+13082;EGYPTIAN HIEROGLYPH D012;Lo;0;L;;;;;N;;;;;
+13083;EGYPTIAN HIEROGLYPH D013;Lo;0;L;;;;;N;;;;;
+13084;EGYPTIAN HIEROGLYPH D014;Lo;0;L;;;;;N;;;;;
+13085;EGYPTIAN HIEROGLYPH D015;Lo;0;L;;;;;N;;;;;
+13086;EGYPTIAN HIEROGLYPH D016;Lo;0;L;;;;;N;;;;;
+13087;EGYPTIAN HIEROGLYPH D017;Lo;0;L;;;;;N;;;;;
+13088;EGYPTIAN HIEROGLYPH D018;Lo;0;L;;;;;N;;;;;
+13089;EGYPTIAN HIEROGLYPH D019;Lo;0;L;;;;;N;;;;;
+1308A;EGYPTIAN HIEROGLYPH D020;Lo;0;L;;;;;N;;;;;
+1308B;EGYPTIAN HIEROGLYPH D021;Lo;0;L;;;;;N;;;;;
+1308C;EGYPTIAN HIEROGLYPH D022;Lo;0;L;;;;;N;;;;;
+1308D;EGYPTIAN HIEROGLYPH D023;Lo;0;L;;;;;N;;;;;
+1308E;EGYPTIAN HIEROGLYPH D024;Lo;0;L;;;;;N;;;;;
+1308F;EGYPTIAN HIEROGLYPH D025;Lo;0;L;;;;;N;;;;;
+13090;EGYPTIAN HIEROGLYPH D026;Lo;0;L;;;;;N;;;;;
+13091;EGYPTIAN HIEROGLYPH D027;Lo;0;L;;;;;N;;;;;
+13092;EGYPTIAN HIEROGLYPH D027A;Lo;0;L;;;;;N;;;;;
+13093;EGYPTIAN HIEROGLYPH D028;Lo;0;L;;;;;N;;;;;
+13094;EGYPTIAN HIEROGLYPH D029;Lo;0;L;;;;;N;;;;;
+13095;EGYPTIAN HIEROGLYPH D030;Lo;0;L;;;;;N;;;;;
+13096;EGYPTIAN HIEROGLYPH D031;Lo;0;L;;;;;N;;;;;
+13097;EGYPTIAN HIEROGLYPH D031A;Lo;0;L;;;;;N;;;;;
+13098;EGYPTIAN HIEROGLYPH D032;Lo;0;L;;;;;N;;;;;
+13099;EGYPTIAN HIEROGLYPH D033;Lo;0;L;;;;;N;;;;;
+1309A;EGYPTIAN HIEROGLYPH D034;Lo;0;L;;;;;N;;;;;
+1309B;EGYPTIAN HIEROGLYPH D034A;Lo;0;L;;;;;N;;;;;
+1309C;EGYPTIAN HIEROGLYPH D035;Lo;0;L;;;;;N;;;;;
+1309D;EGYPTIAN HIEROGLYPH D036;Lo;0;L;;;;;N;;;;;
+1309E;EGYPTIAN HIEROGLYPH D037;Lo;0;L;;;;;N;;;;;
+1309F;EGYPTIAN HIEROGLYPH D038;Lo;0;L;;;;;N;;;;;
+130A0;EGYPTIAN HIEROGLYPH D039;Lo;0;L;;;;;N;;;;;
+130A1;EGYPTIAN HIEROGLYPH D040;Lo;0;L;;;;;N;;;;;
+130A2;EGYPTIAN HIEROGLYPH D041;Lo;0;L;;;;;N;;;;;
+130A3;EGYPTIAN HIEROGLYPH D042;Lo;0;L;;;;;N;;;;;
+130A4;EGYPTIAN HIEROGLYPH D043;Lo;0;L;;;;;N;;;;;
+130A5;EGYPTIAN HIEROGLYPH D044;Lo;0;L;;;;;N;;;;;
+130A6;EGYPTIAN HIEROGLYPH D045;Lo;0;L;;;;;N;;;;;
+130A7;EGYPTIAN HIEROGLYPH D046;Lo;0;L;;;;;N;;;;;
+130A8;EGYPTIAN HIEROGLYPH D046A;Lo;0;L;;;;;N;;;;;
+130A9;EGYPTIAN HIEROGLYPH D047;Lo;0;L;;;;;N;;;;;
+130AA;EGYPTIAN HIEROGLYPH D048;Lo;0;L;;;;;N;;;;;
+130AB;EGYPTIAN HIEROGLYPH D048A;Lo;0;L;;;;;N;;;;;
+130AC;EGYPTIAN HIEROGLYPH D049;Lo;0;L;;;;;N;;;;;
+130AD;EGYPTIAN HIEROGLYPH D050;Lo;0;L;;;;;N;;;;;
+130AE;EGYPTIAN HIEROGLYPH D050A;Lo;0;L;;;;;N;;;;;
+130AF;EGYPTIAN HIEROGLYPH D050B;Lo;0;L;;;;;N;;;;;
+130B0;EGYPTIAN HIEROGLYPH D050C;Lo;0;L;;;;;N;;;;;
+130B1;EGYPTIAN HIEROGLYPH D050D;Lo;0;L;;;;;N;;;;;
+130B2;EGYPTIAN HIEROGLYPH D050E;Lo;0;L;;;;;N;;;;;
+130B3;EGYPTIAN HIEROGLYPH D050F;Lo;0;L;;;;;N;;;;;
+130B4;EGYPTIAN HIEROGLYPH D050G;Lo;0;L;;;;;N;;;;;
+130B5;EGYPTIAN HIEROGLYPH D050H;Lo;0;L;;;;;N;;;;;
+130B6;EGYPTIAN HIEROGLYPH D050I;Lo;0;L;;;;;N;;;;;
+130B7;EGYPTIAN HIEROGLYPH D051;Lo;0;L;;;;;N;;;;;
+130B8;EGYPTIAN HIEROGLYPH D052;Lo;0;L;;;;;N;;;;;
+130B9;EGYPTIAN HIEROGLYPH D052A;Lo;0;L;;;;;N;;;;;
+130BA;EGYPTIAN HIEROGLYPH D053;Lo;0;L;;;;;N;;;;;
+130BB;EGYPTIAN HIEROGLYPH D054;Lo;0;L;;;;;N;;;;;
+130BC;EGYPTIAN HIEROGLYPH D054A;Lo;0;L;;;;;N;;;;;
+130BD;EGYPTIAN HIEROGLYPH D055;Lo;0;L;;;;;N;;;;;
+130BE;EGYPTIAN HIEROGLYPH D056;Lo;0;L;;;;;N;;;;;
+130BF;EGYPTIAN HIEROGLYPH D057;Lo;0;L;;;;;N;;;;;
+130C0;EGYPTIAN HIEROGLYPH D058;Lo;0;L;;;;;N;;;;;
+130C1;EGYPTIAN HIEROGLYPH D059;Lo;0;L;;;;;N;;;;;
+130C2;EGYPTIAN HIEROGLYPH D060;Lo;0;L;;;;;N;;;;;
+130C3;EGYPTIAN HIEROGLYPH D061;Lo;0;L;;;;;N;;;;;
+130C4;EGYPTIAN HIEROGLYPH D062;Lo;0;L;;;;;N;;;;;
+130C5;EGYPTIAN HIEROGLYPH D063;Lo;0;L;;;;;N;;;;;
+130C6;EGYPTIAN HIEROGLYPH D064;Lo;0;L;;;;;N;;;;;
+130C7;EGYPTIAN HIEROGLYPH D065;Lo;0;L;;;;;N;;;;;
+130C8;EGYPTIAN HIEROGLYPH D066;Lo;0;L;;;;;N;;;;;
+130C9;EGYPTIAN HIEROGLYPH D067;Lo;0;L;;;;;N;;;;;
+130CA;EGYPTIAN HIEROGLYPH D067A;Lo;0;L;;;;;N;;;;;
+130CB;EGYPTIAN HIEROGLYPH D067B;Lo;0;L;;;;;N;;;;;
+130CC;EGYPTIAN HIEROGLYPH D067C;Lo;0;L;;;;;N;;;;;
+130CD;EGYPTIAN HIEROGLYPH D067D;Lo;0;L;;;;;N;;;;;
+130CE;EGYPTIAN HIEROGLYPH D067E;Lo;0;L;;;;;N;;;;;
+130CF;EGYPTIAN HIEROGLYPH D067F;Lo;0;L;;;;;N;;;;;
+130D0;EGYPTIAN HIEROGLYPH D067G;Lo;0;L;;;;;N;;;;;
+130D1;EGYPTIAN HIEROGLYPH D067H;Lo;0;L;;;;;N;;;;;
+130D2;EGYPTIAN HIEROGLYPH E001;Lo;0;L;;;;;N;;;;;
+130D3;EGYPTIAN HIEROGLYPH E002;Lo;0;L;;;;;N;;;;;
+130D4;EGYPTIAN HIEROGLYPH E003;Lo;0;L;;;;;N;;;;;
+130D5;EGYPTIAN HIEROGLYPH E004;Lo;0;L;;;;;N;;;;;
+130D6;EGYPTIAN HIEROGLYPH E005;Lo;0;L;;;;;N;;;;;
+130D7;EGYPTIAN HIEROGLYPH E006;Lo;0;L;;;;;N;;;;;
+130D8;EGYPTIAN HIEROGLYPH E007;Lo;0;L;;;;;N;;;;;
+130D9;EGYPTIAN HIEROGLYPH E008;Lo;0;L;;;;;N;;;;;
+130DA;EGYPTIAN HIEROGLYPH E008A;Lo;0;L;;;;;N;;;;;
+130DB;EGYPTIAN HIEROGLYPH E009;Lo;0;L;;;;;N;;;;;
+130DC;EGYPTIAN HIEROGLYPH E009A;Lo;0;L;;;;;N;;;;;
+130DD;EGYPTIAN HIEROGLYPH E010;Lo;0;L;;;;;N;;;;;
+130DE;EGYPTIAN HIEROGLYPH E011;Lo;0;L;;;;;N;;;;;
+130DF;EGYPTIAN HIEROGLYPH E012;Lo;0;L;;;;;N;;;;;
+130E0;EGYPTIAN HIEROGLYPH E013;Lo;0;L;;;;;N;;;;;
+130E1;EGYPTIAN HIEROGLYPH E014;Lo;0;L;;;;;N;;;;;
+130E2;EGYPTIAN HIEROGLYPH E015;Lo;0;L;;;;;N;;;;;
+130E3;EGYPTIAN HIEROGLYPH E016;Lo;0;L;;;;;N;;;;;
+130E4;EGYPTIAN HIEROGLYPH E016A;Lo;0;L;;;;;N;;;;;
+130E5;EGYPTIAN HIEROGLYPH E017;Lo;0;L;;;;;N;;;;;
+130E6;EGYPTIAN HIEROGLYPH E017A;Lo;0;L;;;;;N;;;;;
+130E7;EGYPTIAN HIEROGLYPH E018;Lo;0;L;;;;;N;;;;;
+130E8;EGYPTIAN HIEROGLYPH E019;Lo;0;L;;;;;N;;;;;
+130E9;EGYPTIAN HIEROGLYPH E020;Lo;0;L;;;;;N;;;;;
+130EA;EGYPTIAN HIEROGLYPH E020A;Lo;0;L;;;;;N;;;;;
+130EB;EGYPTIAN HIEROGLYPH E021;Lo;0;L;;;;;N;;;;;
+130EC;EGYPTIAN HIEROGLYPH E022;Lo;0;L;;;;;N;;;;;
+130ED;EGYPTIAN HIEROGLYPH E023;Lo;0;L;;;;;N;;;;;
+130EE;EGYPTIAN HIEROGLYPH E024;Lo;0;L;;;;;N;;;;;
+130EF;EGYPTIAN HIEROGLYPH E025;Lo;0;L;;;;;N;;;;;
+130F0;EGYPTIAN HIEROGLYPH E026;Lo;0;L;;;;;N;;;;;
+130F1;EGYPTIAN HIEROGLYPH E027;Lo;0;L;;;;;N;;;;;
+130F2;EGYPTIAN HIEROGLYPH E028;Lo;0;L;;;;;N;;;;;
+130F3;EGYPTIAN HIEROGLYPH E028A;Lo;0;L;;;;;N;;;;;
+130F4;EGYPTIAN HIEROGLYPH E029;Lo;0;L;;;;;N;;;;;
+130F5;EGYPTIAN HIEROGLYPH E030;Lo;0;L;;;;;N;;;;;
+130F6;EGYPTIAN HIEROGLYPH E031;Lo;0;L;;;;;N;;;;;
+130F7;EGYPTIAN HIEROGLYPH E032;Lo;0;L;;;;;N;;;;;
+130F8;EGYPTIAN HIEROGLYPH E033;Lo;0;L;;;;;N;;;;;
+130F9;EGYPTIAN HIEROGLYPH E034;Lo;0;L;;;;;N;;;;;
+130FA;EGYPTIAN HIEROGLYPH E034A;Lo;0;L;;;;;N;;;;;
+130FB;EGYPTIAN HIEROGLYPH E036;Lo;0;L;;;;;N;;;;;
+130FC;EGYPTIAN HIEROGLYPH E037;Lo;0;L;;;;;N;;;;;
+130FD;EGYPTIAN HIEROGLYPH E038;Lo;0;L;;;;;N;;;;;
+130FE;EGYPTIAN HIEROGLYPH F001;Lo;0;L;;;;;N;;;;;
+130FF;EGYPTIAN HIEROGLYPH F001A;Lo;0;L;;;;;N;;;;;
+13100;EGYPTIAN HIEROGLYPH F002;Lo;0;L;;;;;N;;;;;
+13101;EGYPTIAN HIEROGLYPH F003;Lo;0;L;;;;;N;;;;;
+13102;EGYPTIAN HIEROGLYPH F004;Lo;0;L;;;;;N;;;;;
+13103;EGYPTIAN HIEROGLYPH F005;Lo;0;L;;;;;N;;;;;
+13104;EGYPTIAN HIEROGLYPH F006;Lo;0;L;;;;;N;;;;;
+13105;EGYPTIAN HIEROGLYPH F007;Lo;0;L;;;;;N;;;;;
+13106;EGYPTIAN HIEROGLYPH F008;Lo;0;L;;;;;N;;;;;
+13107;EGYPTIAN HIEROGLYPH F009;Lo;0;L;;;;;N;;;;;
+13108;EGYPTIAN HIEROGLYPH F010;Lo;0;L;;;;;N;;;;;
+13109;EGYPTIAN HIEROGLYPH F011;Lo;0;L;;;;;N;;;;;
+1310A;EGYPTIAN HIEROGLYPH F012;Lo;0;L;;;;;N;;;;;
+1310B;EGYPTIAN HIEROGLYPH F013;Lo;0;L;;;;;N;;;;;
+1310C;EGYPTIAN HIEROGLYPH F013A;Lo;0;L;;;;;N;;;;;
+1310D;EGYPTIAN HIEROGLYPH F014;Lo;0;L;;;;;N;;;;;
+1310E;EGYPTIAN HIEROGLYPH F015;Lo;0;L;;;;;N;;;;;
+1310F;EGYPTIAN HIEROGLYPH F016;Lo;0;L;;;;;N;;;;;
+13110;EGYPTIAN HIEROGLYPH F017;Lo;0;L;;;;;N;;;;;
+13111;EGYPTIAN HIEROGLYPH F018;Lo;0;L;;;;;N;;;;;
+13112;EGYPTIAN HIEROGLYPH F019;Lo;0;L;;;;;N;;;;;
+13113;EGYPTIAN HIEROGLYPH F020;Lo;0;L;;;;;N;;;;;
+13114;EGYPTIAN HIEROGLYPH F021;Lo;0;L;;;;;N;;;;;
+13115;EGYPTIAN HIEROGLYPH F021A;Lo;0;L;;;;;N;;;;;
+13116;EGYPTIAN HIEROGLYPH F022;Lo;0;L;;;;;N;;;;;
+13117;EGYPTIAN HIEROGLYPH F023;Lo;0;L;;;;;N;;;;;
+13118;EGYPTIAN HIEROGLYPH F024;Lo;0;L;;;;;N;;;;;
+13119;EGYPTIAN HIEROGLYPH F025;Lo;0;L;;;;;N;;;;;
+1311A;EGYPTIAN HIEROGLYPH F026;Lo;0;L;;;;;N;;;;;
+1311B;EGYPTIAN HIEROGLYPH F027;Lo;0;L;;;;;N;;;;;
+1311C;EGYPTIAN HIEROGLYPH F028;Lo;0;L;;;;;N;;;;;
+1311D;EGYPTIAN HIEROGLYPH F029;Lo;0;L;;;;;N;;;;;
+1311E;EGYPTIAN HIEROGLYPH F030;Lo;0;L;;;;;N;;;;;
+1311F;EGYPTIAN HIEROGLYPH F031;Lo;0;L;;;;;N;;;;;
+13120;EGYPTIAN HIEROGLYPH F031A;Lo;0;L;;;;;N;;;;;
+13121;EGYPTIAN HIEROGLYPH F032;Lo;0;L;;;;;N;;;;;
+13122;EGYPTIAN HIEROGLYPH F033;Lo;0;L;;;;;N;;;;;
+13123;EGYPTIAN HIEROGLYPH F034;Lo;0;L;;;;;N;;;;;
+13124;EGYPTIAN HIEROGLYPH F035;Lo;0;L;;;;;N;;;;;
+13125;EGYPTIAN HIEROGLYPH F036;Lo;0;L;;;;;N;;;;;
+13126;EGYPTIAN HIEROGLYPH F037;Lo;0;L;;;;;N;;;;;
+13127;EGYPTIAN HIEROGLYPH F037A;Lo;0;L;;;;;N;;;;;
+13128;EGYPTIAN HIEROGLYPH F038;Lo;0;L;;;;;N;;;;;
+13129;EGYPTIAN HIEROGLYPH F038A;Lo;0;L;;;;;N;;;;;
+1312A;EGYPTIAN HIEROGLYPH F039;Lo;0;L;;;;;N;;;;;
+1312B;EGYPTIAN HIEROGLYPH F040;Lo;0;L;;;;;N;;;;;
+1312C;EGYPTIAN HIEROGLYPH F041;Lo;0;L;;;;;N;;;;;
+1312D;EGYPTIAN HIEROGLYPH F042;Lo;0;L;;;;;N;;;;;
+1312E;EGYPTIAN HIEROGLYPH F043;Lo;0;L;;;;;N;;;;;
+1312F;EGYPTIAN HIEROGLYPH F044;Lo;0;L;;;;;N;;;;;
+13130;EGYPTIAN HIEROGLYPH F045;Lo;0;L;;;;;N;;;;;
+13131;EGYPTIAN HIEROGLYPH F045A;Lo;0;L;;;;;N;;;;;
+13132;EGYPTIAN HIEROGLYPH F046;Lo;0;L;;;;;N;;;;;
+13133;EGYPTIAN HIEROGLYPH F046A;Lo;0;L;;;;;N;;;;;
+13134;EGYPTIAN HIEROGLYPH F047;Lo;0;L;;;;;N;;;;;
+13135;EGYPTIAN HIEROGLYPH F047A;Lo;0;L;;;;;N;;;;;
+13136;EGYPTIAN HIEROGLYPH F048;Lo;0;L;;;;;N;;;;;
+13137;EGYPTIAN HIEROGLYPH F049;Lo;0;L;;;;;N;;;;;
+13138;EGYPTIAN HIEROGLYPH F050;Lo;0;L;;;;;N;;;;;
+13139;EGYPTIAN HIEROGLYPH F051;Lo;0;L;;;;;N;;;;;
+1313A;EGYPTIAN HIEROGLYPH F051A;Lo;0;L;;;;;N;;;;;
+1313B;EGYPTIAN HIEROGLYPH F051B;Lo;0;L;;;;;N;;;;;
+1313C;EGYPTIAN HIEROGLYPH F051C;Lo;0;L;;;;;N;;;;;
+1313D;EGYPTIAN HIEROGLYPH F052;Lo;0;L;;;;;N;;;;;
+1313E;EGYPTIAN HIEROGLYPH F053;Lo;0;L;;;;;N;;;;;
+1313F;EGYPTIAN HIEROGLYPH G001;Lo;0;L;;;;;N;;;;;
+13140;EGYPTIAN HIEROGLYPH G002;Lo;0;L;;;;;N;;;;;
+13141;EGYPTIAN HIEROGLYPH G003;Lo;0;L;;;;;N;;;;;
+13142;EGYPTIAN HIEROGLYPH G004;Lo;0;L;;;;;N;;;;;
+13143;EGYPTIAN HIEROGLYPH G005;Lo;0;L;;;;;N;;;;;
+13144;EGYPTIAN HIEROGLYPH G006;Lo;0;L;;;;;N;;;;;
+13145;EGYPTIAN HIEROGLYPH G006A;Lo;0;L;;;;;N;;;;;
+13146;EGYPTIAN HIEROGLYPH G007;Lo;0;L;;;;;N;;;;;
+13147;EGYPTIAN HIEROGLYPH G007A;Lo;0;L;;;;;N;;;;;
+13148;EGYPTIAN HIEROGLYPH G007B;Lo;0;L;;;;;N;;;;;
+13149;EGYPTIAN HIEROGLYPH G008;Lo;0;L;;;;;N;;;;;
+1314A;EGYPTIAN HIEROGLYPH G009;Lo;0;L;;;;;N;;;;;
+1314B;EGYPTIAN HIEROGLYPH G010;Lo;0;L;;;;;N;;;;;
+1314C;EGYPTIAN HIEROGLYPH G011;Lo;0;L;;;;;N;;;;;
+1314D;EGYPTIAN HIEROGLYPH G011A;Lo;0;L;;;;;N;;;;;
+1314E;EGYPTIAN HIEROGLYPH G012;Lo;0;L;;;;;N;;;;;
+1314F;EGYPTIAN HIEROGLYPH G013;Lo;0;L;;;;;N;;;;;
+13150;EGYPTIAN HIEROGLYPH G014;Lo;0;L;;;;;N;;;;;
+13151;EGYPTIAN HIEROGLYPH G015;Lo;0;L;;;;;N;;;;;
+13152;EGYPTIAN HIEROGLYPH G016;Lo;0;L;;;;;N;;;;;
+13153;EGYPTIAN HIEROGLYPH G017;Lo;0;L;;;;;N;;;;;
+13154;EGYPTIAN HIEROGLYPH G018;Lo;0;L;;;;;N;;;;;
+13155;EGYPTIAN HIEROGLYPH G019;Lo;0;L;;;;;N;;;;;
+13156;EGYPTIAN HIEROGLYPH G020;Lo;0;L;;;;;N;;;;;
+13157;EGYPTIAN HIEROGLYPH G020A;Lo;0;L;;;;;N;;;;;
+13158;EGYPTIAN HIEROGLYPH G021;Lo;0;L;;;;;N;;;;;
+13159;EGYPTIAN HIEROGLYPH G022;Lo;0;L;;;;;N;;;;;
+1315A;EGYPTIAN HIEROGLYPH G023;Lo;0;L;;;;;N;;;;;
+1315B;EGYPTIAN HIEROGLYPH G024;Lo;0;L;;;;;N;;;;;
+1315C;EGYPTIAN HIEROGLYPH G025;Lo;0;L;;;;;N;;;;;
+1315D;EGYPTIAN HIEROGLYPH G026;Lo;0;L;;;;;N;;;;;
+1315E;EGYPTIAN HIEROGLYPH G026A;Lo;0;L;;;;;N;;;;;
+1315F;EGYPTIAN HIEROGLYPH G027;Lo;0;L;;;;;N;;;;;
+13160;EGYPTIAN HIEROGLYPH G028;Lo;0;L;;;;;N;;;;;
+13161;EGYPTIAN HIEROGLYPH G029;Lo;0;L;;;;;N;;;;;
+13162;EGYPTIAN HIEROGLYPH G030;Lo;0;L;;;;;N;;;;;
+13163;EGYPTIAN HIEROGLYPH G031;Lo;0;L;;;;;N;;;;;
+13164;EGYPTIAN HIEROGLYPH G032;Lo;0;L;;;;;N;;;;;
+13165;EGYPTIAN HIEROGLYPH G033;Lo;0;L;;;;;N;;;;;
+13166;EGYPTIAN HIEROGLYPH G034;Lo;0;L;;;;;N;;;;;
+13167;EGYPTIAN HIEROGLYPH G035;Lo;0;L;;;;;N;;;;;
+13168;EGYPTIAN HIEROGLYPH G036;Lo;0;L;;;;;N;;;;;
+13169;EGYPTIAN HIEROGLYPH G036A;Lo;0;L;;;;;N;;;;;
+1316A;EGYPTIAN HIEROGLYPH G037;Lo;0;L;;;;;N;;;;;
+1316B;EGYPTIAN HIEROGLYPH G037A;Lo;0;L;;;;;N;;;;;
+1316C;EGYPTIAN HIEROGLYPH G038;Lo;0;L;;;;;N;;;;;
+1316D;EGYPTIAN HIEROGLYPH G039;Lo;0;L;;;;;N;;;;;
+1316E;EGYPTIAN HIEROGLYPH G040;Lo;0;L;;;;;N;;;;;
+1316F;EGYPTIAN HIEROGLYPH G041;Lo;0;L;;;;;N;;;;;
+13170;EGYPTIAN HIEROGLYPH G042;Lo;0;L;;;;;N;;;;;
+13171;EGYPTIAN HIEROGLYPH G043;Lo;0;L;;;;;N;;;;;
+13172;EGYPTIAN HIEROGLYPH G043A;Lo;0;L;;;;;N;;;;;
+13173;EGYPTIAN HIEROGLYPH G044;Lo;0;L;;;;;N;;;;;
+13174;EGYPTIAN HIEROGLYPH G045;Lo;0;L;;;;;N;;;;;
+13175;EGYPTIAN HIEROGLYPH G045A;Lo;0;L;;;;;N;;;;;
+13176;EGYPTIAN HIEROGLYPH G046;Lo;0;L;;;;;N;;;;;
+13177;EGYPTIAN HIEROGLYPH G047;Lo;0;L;;;;;N;;;;;
+13178;EGYPTIAN HIEROGLYPH G048;Lo;0;L;;;;;N;;;;;
+13179;EGYPTIAN HIEROGLYPH G049;Lo;0;L;;;;;N;;;;;
+1317A;EGYPTIAN HIEROGLYPH G050;Lo;0;L;;;;;N;;;;;
+1317B;EGYPTIAN HIEROGLYPH G051;Lo;0;L;;;;;N;;;;;
+1317C;EGYPTIAN HIEROGLYPH G052;Lo;0;L;;;;;N;;;;;
+1317D;EGYPTIAN HIEROGLYPH G053;Lo;0;L;;;;;N;;;;;
+1317E;EGYPTIAN HIEROGLYPH G054;Lo;0;L;;;;;N;;;;;
+1317F;EGYPTIAN HIEROGLYPH H001;Lo;0;L;;;;;N;;;;;
+13180;EGYPTIAN HIEROGLYPH H002;Lo;0;L;;;;;N;;;;;
+13181;EGYPTIAN HIEROGLYPH H003;Lo;0;L;;;;;N;;;;;
+13182;EGYPTIAN HIEROGLYPH H004;Lo;0;L;;;;;N;;;;;
+13183;EGYPTIAN HIEROGLYPH H005;Lo;0;L;;;;;N;;;;;
+13184;EGYPTIAN HIEROGLYPH H006;Lo;0;L;;;;;N;;;;;
+13185;EGYPTIAN HIEROGLYPH H006A;Lo;0;L;;;;;N;;;;;
+13186;EGYPTIAN HIEROGLYPH H007;Lo;0;L;;;;;N;;;;;
+13187;EGYPTIAN HIEROGLYPH H008;Lo;0;L;;;;;N;;;;;
+13188;EGYPTIAN HIEROGLYPH I001;Lo;0;L;;;;;N;;;;;
+13189;EGYPTIAN HIEROGLYPH I002;Lo;0;L;;;;;N;;;;;
+1318A;EGYPTIAN HIEROGLYPH I003;Lo;0;L;;;;;N;;;;;
+1318B;EGYPTIAN HIEROGLYPH I004;Lo;0;L;;;;;N;;;;;
+1318C;EGYPTIAN HIEROGLYPH I005;Lo;0;L;;;;;N;;;;;
+1318D;EGYPTIAN HIEROGLYPH I005A;Lo;0;L;;;;;N;;;;;
+1318E;EGYPTIAN HIEROGLYPH I006;Lo;0;L;;;;;N;;;;;
+1318F;EGYPTIAN HIEROGLYPH I007;Lo;0;L;;;;;N;;;;;
+13190;EGYPTIAN HIEROGLYPH I008;Lo;0;L;;;;;N;;;;;
+13191;EGYPTIAN HIEROGLYPH I009;Lo;0;L;;;;;N;;;;;
+13192;EGYPTIAN HIEROGLYPH I009A;Lo;0;L;;;;;N;;;;;
+13193;EGYPTIAN HIEROGLYPH I010;Lo;0;L;;;;;N;;;;;
+13194;EGYPTIAN HIEROGLYPH I010A;Lo;0;L;;;;;N;;;;;
+13195;EGYPTIAN HIEROGLYPH I011;Lo;0;L;;;;;N;;;;;
+13196;EGYPTIAN HIEROGLYPH I011A;Lo;0;L;;;;;N;;;;;
+13197;EGYPTIAN HIEROGLYPH I012;Lo;0;L;;;;;N;;;;;
+13198;EGYPTIAN HIEROGLYPH I013;Lo;0;L;;;;;N;;;;;
+13199;EGYPTIAN HIEROGLYPH I014;Lo;0;L;;;;;N;;;;;
+1319A;EGYPTIAN HIEROGLYPH I015;Lo;0;L;;;;;N;;;;;
+1319B;EGYPTIAN HIEROGLYPH K001;Lo;0;L;;;;;N;;;;;
+1319C;EGYPTIAN HIEROGLYPH K002;Lo;0;L;;;;;N;;;;;
+1319D;EGYPTIAN HIEROGLYPH K003;Lo;0;L;;;;;N;;;;;
+1319E;EGYPTIAN HIEROGLYPH K004;Lo;0;L;;;;;N;;;;;
+1319F;EGYPTIAN HIEROGLYPH K005;Lo;0;L;;;;;N;;;;;
+131A0;EGYPTIAN HIEROGLYPH K006;Lo;0;L;;;;;N;;;;;
+131A1;EGYPTIAN HIEROGLYPH K007;Lo;0;L;;;;;N;;;;;
+131A2;EGYPTIAN HIEROGLYPH K008;Lo;0;L;;;;;N;;;;;
+131A3;EGYPTIAN HIEROGLYPH L001;Lo;0;L;;;;;N;;;;;
+131A4;EGYPTIAN HIEROGLYPH L002;Lo;0;L;;;;;N;;;;;
+131A5;EGYPTIAN HIEROGLYPH L002A;Lo;0;L;;;;;N;;;;;
+131A6;EGYPTIAN HIEROGLYPH L003;Lo;0;L;;;;;N;;;;;
+131A7;EGYPTIAN HIEROGLYPH L004;Lo;0;L;;;;;N;;;;;
+131A8;EGYPTIAN HIEROGLYPH L005;Lo;0;L;;;;;N;;;;;
+131A9;EGYPTIAN HIEROGLYPH L006;Lo;0;L;;;;;N;;;;;
+131AA;EGYPTIAN HIEROGLYPH L006A;Lo;0;L;;;;;N;;;;;
+131AB;EGYPTIAN HIEROGLYPH L007;Lo;0;L;;;;;N;;;;;
+131AC;EGYPTIAN HIEROGLYPH L008;Lo;0;L;;;;;N;;;;;
+131AD;EGYPTIAN HIEROGLYPH M001;Lo;0;L;;;;;N;;;;;
+131AE;EGYPTIAN HIEROGLYPH M001A;Lo;0;L;;;;;N;;;;;
+131AF;EGYPTIAN HIEROGLYPH M001B;Lo;0;L;;;;;N;;;;;
+131B0;EGYPTIAN HIEROGLYPH M002;Lo;0;L;;;;;N;;;;;
+131B1;EGYPTIAN HIEROGLYPH M003;Lo;0;L;;;;;N;;;;;
+131B2;EGYPTIAN HIEROGLYPH M003A;Lo;0;L;;;;;N;;;;;
+131B3;EGYPTIAN HIEROGLYPH M004;Lo;0;L;;;;;N;;;;;
+131B4;EGYPTIAN HIEROGLYPH M005;Lo;0;L;;;;;N;;;;;
+131B5;EGYPTIAN HIEROGLYPH M006;Lo;0;L;;;;;N;;;;;
+131B6;EGYPTIAN HIEROGLYPH M007;Lo;0;L;;;;;N;;;;;
+131B7;EGYPTIAN HIEROGLYPH M008;Lo;0;L;;;;;N;;;;;
+131B8;EGYPTIAN HIEROGLYPH M009;Lo;0;L;;;;;N;;;;;
+131B9;EGYPTIAN HIEROGLYPH M010;Lo;0;L;;;;;N;;;;;
+131BA;EGYPTIAN HIEROGLYPH M010A;Lo;0;L;;;;;N;;;;;
+131BB;EGYPTIAN HIEROGLYPH M011;Lo;0;L;;;;;N;;;;;
+131BC;EGYPTIAN HIEROGLYPH M012;Lo;0;L;;;;;N;;;;;
+131BD;EGYPTIAN HIEROGLYPH M012A;Lo;0;L;;;;;N;;;;;
+131BE;EGYPTIAN HIEROGLYPH M012B;Lo;0;L;;;;;N;;;;;
+131BF;EGYPTIAN HIEROGLYPH M012C;Lo;0;L;;;;;N;;;;;
+131C0;EGYPTIAN HIEROGLYPH M012D;Lo;0;L;;;;;N;;;;;
+131C1;EGYPTIAN HIEROGLYPH M012E;Lo;0;L;;;;;N;;;;;
+131C2;EGYPTIAN HIEROGLYPH M012F;Lo;0;L;;;;;N;;;;;
+131C3;EGYPTIAN HIEROGLYPH M012G;Lo;0;L;;;;;N;;;;;
+131C4;EGYPTIAN HIEROGLYPH M012H;Lo;0;L;;;;;N;;;;;
+131C5;EGYPTIAN HIEROGLYPH M013;Lo;0;L;;;;;N;;;;;
+131C6;EGYPTIAN HIEROGLYPH M014;Lo;0;L;;;;;N;;;;;
+131C7;EGYPTIAN HIEROGLYPH M015;Lo;0;L;;;;;N;;;;;
+131C8;EGYPTIAN HIEROGLYPH M015A;Lo;0;L;;;;;N;;;;;
+131C9;EGYPTIAN HIEROGLYPH M016;Lo;0;L;;;;;N;;;;;
+131CA;EGYPTIAN HIEROGLYPH M016A;Lo;0;L;;;;;N;;;;;
+131CB;EGYPTIAN HIEROGLYPH M017;Lo;0;L;;;;;N;;;;;
+131CC;EGYPTIAN HIEROGLYPH M017A;Lo;0;L;;;;;N;;;;;
+131CD;EGYPTIAN HIEROGLYPH M018;Lo;0;L;;;;;N;;;;;
+131CE;EGYPTIAN HIEROGLYPH M019;Lo;0;L;;;;;N;;;;;
+131CF;EGYPTIAN HIEROGLYPH M020;Lo;0;L;;;;;N;;;;;
+131D0;EGYPTIAN HIEROGLYPH M021;Lo;0;L;;;;;N;;;;;
+131D1;EGYPTIAN HIEROGLYPH M022;Lo;0;L;;;;;N;;;;;
+131D2;EGYPTIAN HIEROGLYPH M022A;Lo;0;L;;;;;N;;;;;
+131D3;EGYPTIAN HIEROGLYPH M023;Lo;0;L;;;;;N;;;;;
+131D4;EGYPTIAN HIEROGLYPH M024;Lo;0;L;;;;;N;;;;;
+131D5;EGYPTIAN HIEROGLYPH M024A;Lo;0;L;;;;;N;;;;;
+131D6;EGYPTIAN HIEROGLYPH M025;Lo;0;L;;;;;N;;;;;
+131D7;EGYPTIAN HIEROGLYPH M026;Lo;0;L;;;;;N;;;;;
+131D8;EGYPTIAN HIEROGLYPH M027;Lo;0;L;;;;;N;;;;;
+131D9;EGYPTIAN HIEROGLYPH M028;Lo;0;L;;;;;N;;;;;
+131DA;EGYPTIAN HIEROGLYPH M028A;Lo;0;L;;;;;N;;;;;
+131DB;EGYPTIAN HIEROGLYPH M029;Lo;0;L;;;;;N;;;;;
+131DC;EGYPTIAN HIEROGLYPH M030;Lo;0;L;;;;;N;;;;;
+131DD;EGYPTIAN HIEROGLYPH M031;Lo;0;L;;;;;N;;;;;
+131DE;EGYPTIAN HIEROGLYPH M031A;Lo;0;L;;;;;N;;;;;
+131DF;EGYPTIAN HIEROGLYPH M032;Lo;0;L;;;;;N;;;;;
+131E0;EGYPTIAN HIEROGLYPH M033;Lo;0;L;;;;;N;;;;;
+131E1;EGYPTIAN HIEROGLYPH M033A;Lo;0;L;;;;;N;;;;;
+131E2;EGYPTIAN HIEROGLYPH M033B;Lo;0;L;;;;;N;;;;;
+131E3;EGYPTIAN HIEROGLYPH M034;Lo;0;L;;;;;N;;;;;
+131E4;EGYPTIAN HIEROGLYPH M035;Lo;0;L;;;;;N;;;;;
+131E5;EGYPTIAN HIEROGLYPH M036;Lo;0;L;;;;;N;;;;;
+131E6;EGYPTIAN HIEROGLYPH M037;Lo;0;L;;;;;N;;;;;
+131E7;EGYPTIAN HIEROGLYPH M038;Lo;0;L;;;;;N;;;;;
+131E8;EGYPTIAN HIEROGLYPH M039;Lo;0;L;;;;;N;;;;;
+131E9;EGYPTIAN HIEROGLYPH M040;Lo;0;L;;;;;N;;;;;
+131EA;EGYPTIAN HIEROGLYPH M040A;Lo;0;L;;;;;N;;;;;
+131EB;EGYPTIAN HIEROGLYPH M041;Lo;0;L;;;;;N;;;;;
+131EC;EGYPTIAN HIEROGLYPH M042;Lo;0;L;;;;;N;;;;;
+131ED;EGYPTIAN HIEROGLYPH M043;Lo;0;L;;;;;N;;;;;
+131EE;EGYPTIAN HIEROGLYPH M044;Lo;0;L;;;;;N;;;;;
+131EF;EGYPTIAN HIEROGLYPH N001;Lo;0;L;;;;;N;;;;;
+131F0;EGYPTIAN HIEROGLYPH N002;Lo;0;L;;;;;N;;;;;
+131F1;EGYPTIAN HIEROGLYPH N003;Lo;0;L;;;;;N;;;;;
+131F2;EGYPTIAN HIEROGLYPH N004;Lo;0;L;;;;;N;;;;;
+131F3;EGYPTIAN HIEROGLYPH N005;Lo;0;L;;;;;N;;;;;
+131F4;EGYPTIAN HIEROGLYPH N006;Lo;0;L;;;;;N;;;;;
+131F5;EGYPTIAN HIEROGLYPH N007;Lo;0;L;;;;;N;;;;;
+131F6;EGYPTIAN HIEROGLYPH N008;Lo;0;L;;;;;N;;;;;
+131F7;EGYPTIAN HIEROGLYPH N009;Lo;0;L;;;;;N;;;;;
+131F8;EGYPTIAN HIEROGLYPH N010;Lo;0;L;;;;;N;;;;;
+131F9;EGYPTIAN HIEROGLYPH N011;Lo;0;L;;;;;N;;;;;
+131FA;EGYPTIAN HIEROGLYPH N012;Lo;0;L;;;;;N;;;;;
+131FB;EGYPTIAN HIEROGLYPH N013;Lo;0;L;;;;;N;;;;;
+131FC;EGYPTIAN HIEROGLYPH N014;Lo;0;L;;;;;N;;;;;
+131FD;EGYPTIAN HIEROGLYPH N015;Lo;0;L;;;;;N;;;;;
+131FE;EGYPTIAN HIEROGLYPH N016;Lo;0;L;;;;;N;;;;;
+131FF;EGYPTIAN HIEROGLYPH N017;Lo;0;L;;;;;N;;;;;
+13200;EGYPTIAN HIEROGLYPH N018;Lo;0;L;;;;;N;;;;;
+13201;EGYPTIAN HIEROGLYPH N018A;Lo;0;L;;;;;N;;;;;
+13202;EGYPTIAN HIEROGLYPH N018B;Lo;0;L;;;;;N;;;;;
+13203;EGYPTIAN HIEROGLYPH N019;Lo;0;L;;;;;N;;;;;
+13204;EGYPTIAN HIEROGLYPH N020;Lo;0;L;;;;;N;;;;;
+13205;EGYPTIAN HIEROGLYPH N021;Lo;0;L;;;;;N;;;;;
+13206;EGYPTIAN HIEROGLYPH N022;Lo;0;L;;;;;N;;;;;
+13207;EGYPTIAN HIEROGLYPH N023;Lo;0;L;;;;;N;;;;;
+13208;EGYPTIAN HIEROGLYPH N024;Lo;0;L;;;;;N;;;;;
+13209;EGYPTIAN HIEROGLYPH N025;Lo;0;L;;;;;N;;;;;
+1320A;EGYPTIAN HIEROGLYPH N025A;Lo;0;L;;;;;N;;;;;
+1320B;EGYPTIAN HIEROGLYPH N026;Lo;0;L;;;;;N;;;;;
+1320C;EGYPTIAN HIEROGLYPH N027;Lo;0;L;;;;;N;;;;;
+1320D;EGYPTIAN HIEROGLYPH N028;Lo;0;L;;;;;N;;;;;
+1320E;EGYPTIAN HIEROGLYPH N029;Lo;0;L;;;;;N;;;;;
+1320F;EGYPTIAN HIEROGLYPH N030;Lo;0;L;;;;;N;;;;;
+13210;EGYPTIAN HIEROGLYPH N031;Lo;0;L;;;;;N;;;;;
+13211;EGYPTIAN HIEROGLYPH N032;Lo;0;L;;;;;N;;;;;
+13212;EGYPTIAN HIEROGLYPH N033;Lo;0;L;;;;;N;;;;;
+13213;EGYPTIAN HIEROGLYPH N033A;Lo;0;L;;;;;N;;;;;
+13214;EGYPTIAN HIEROGLYPH N034;Lo;0;L;;;;;N;;;;;
+13215;EGYPTIAN HIEROGLYPH N034A;Lo;0;L;;;;;N;;;;;
+13216;EGYPTIAN HIEROGLYPH N035;Lo;0;L;;;;;N;;;;;
+13217;EGYPTIAN HIEROGLYPH N035A;Lo;0;L;;;;;N;;;;;
+13218;EGYPTIAN HIEROGLYPH N036;Lo;0;L;;;;;N;;;;;
+13219;EGYPTIAN HIEROGLYPH N037;Lo;0;L;;;;;N;;;;;
+1321A;EGYPTIAN HIEROGLYPH N037A;Lo;0;L;;;;;N;;;;;
+1321B;EGYPTIAN HIEROGLYPH N038;Lo;0;L;;;;;N;;;;;
+1321C;EGYPTIAN HIEROGLYPH N039;Lo;0;L;;;;;N;;;;;
+1321D;EGYPTIAN HIEROGLYPH N040;Lo;0;L;;;;;N;;;;;
+1321E;EGYPTIAN HIEROGLYPH N041;Lo;0;L;;;;;N;;;;;
+1321F;EGYPTIAN HIEROGLYPH N042;Lo;0;L;;;;;N;;;;;
+13220;EGYPTIAN HIEROGLYPH NL001;Lo;0;L;;;;;N;;;;;
+13221;EGYPTIAN HIEROGLYPH NL002;Lo;0;L;;;;;N;;;;;
+13222;EGYPTIAN HIEROGLYPH NL003;Lo;0;L;;;;;N;;;;;
+13223;EGYPTIAN HIEROGLYPH NL004;Lo;0;L;;;;;N;;;;;
+13224;EGYPTIAN HIEROGLYPH NL005;Lo;0;L;;;;;N;;;;;
+13225;EGYPTIAN HIEROGLYPH NL005A;Lo;0;L;;;;;N;;;;;
+13226;EGYPTIAN HIEROGLYPH NL006;Lo;0;L;;;;;N;;;;;
+13227;EGYPTIAN HIEROGLYPH NL007;Lo;0;L;;;;;N;;;;;
+13228;EGYPTIAN HIEROGLYPH NL008;Lo;0;L;;;;;N;;;;;
+13229;EGYPTIAN HIEROGLYPH NL009;Lo;0;L;;;;;N;;;;;
+1322A;EGYPTIAN HIEROGLYPH NL010;Lo;0;L;;;;;N;;;;;
+1322B;EGYPTIAN HIEROGLYPH NL011;Lo;0;L;;;;;N;;;;;
+1322C;EGYPTIAN HIEROGLYPH NL012;Lo;0;L;;;;;N;;;;;
+1322D;EGYPTIAN HIEROGLYPH NL013;Lo;0;L;;;;;N;;;;;
+1322E;EGYPTIAN HIEROGLYPH NL014;Lo;0;L;;;;;N;;;;;
+1322F;EGYPTIAN HIEROGLYPH NL015;Lo;0;L;;;;;N;;;;;
+13230;EGYPTIAN HIEROGLYPH NL016;Lo;0;L;;;;;N;;;;;
+13231;EGYPTIAN HIEROGLYPH NL017;Lo;0;L;;;;;N;;;;;
+13232;EGYPTIAN HIEROGLYPH NL017A;Lo;0;L;;;;;N;;;;;
+13233;EGYPTIAN HIEROGLYPH NL018;Lo;0;L;;;;;N;;;;;
+13234;EGYPTIAN HIEROGLYPH NL019;Lo;0;L;;;;;N;;;;;
+13235;EGYPTIAN HIEROGLYPH NL020;Lo;0;L;;;;;N;;;;;
+13236;EGYPTIAN HIEROGLYPH NU001;Lo;0;L;;;;;N;;;;;
+13237;EGYPTIAN HIEROGLYPH NU002;Lo;0;L;;;;;N;;;;;
+13238;EGYPTIAN HIEROGLYPH NU003;Lo;0;L;;;;;N;;;;;
+13239;EGYPTIAN HIEROGLYPH NU004;Lo;0;L;;;;;N;;;;;
+1323A;EGYPTIAN HIEROGLYPH NU005;Lo;0;L;;;;;N;;;;;
+1323B;EGYPTIAN HIEROGLYPH NU006;Lo;0;L;;;;;N;;;;;
+1323C;EGYPTIAN HIEROGLYPH NU007;Lo;0;L;;;;;N;;;;;
+1323D;EGYPTIAN HIEROGLYPH NU008;Lo;0;L;;;;;N;;;;;
+1323E;EGYPTIAN HIEROGLYPH NU009;Lo;0;L;;;;;N;;;;;
+1323F;EGYPTIAN HIEROGLYPH NU010;Lo;0;L;;;;;N;;;;;
+13240;EGYPTIAN HIEROGLYPH NU010A;Lo;0;L;;;;;N;;;;;
+13241;EGYPTIAN HIEROGLYPH NU011;Lo;0;L;;;;;N;;;;;
+13242;EGYPTIAN HIEROGLYPH NU011A;Lo;0;L;;;;;N;;;;;
+13243;EGYPTIAN HIEROGLYPH NU012;Lo;0;L;;;;;N;;;;;
+13244;EGYPTIAN HIEROGLYPH NU013;Lo;0;L;;;;;N;;;;;
+13245;EGYPTIAN HIEROGLYPH NU014;Lo;0;L;;;;;N;;;;;
+13246;EGYPTIAN HIEROGLYPH NU015;Lo;0;L;;;;;N;;;;;
+13247;EGYPTIAN HIEROGLYPH NU016;Lo;0;L;;;;;N;;;;;
+13248;EGYPTIAN HIEROGLYPH NU017;Lo;0;L;;;;;N;;;;;
+13249;EGYPTIAN HIEROGLYPH NU018;Lo;0;L;;;;;N;;;;;
+1324A;EGYPTIAN HIEROGLYPH NU018A;Lo;0;L;;;;;N;;;;;
+1324B;EGYPTIAN HIEROGLYPH NU019;Lo;0;L;;;;;N;;;;;
+1324C;EGYPTIAN HIEROGLYPH NU020;Lo;0;L;;;;;N;;;;;
+1324D;EGYPTIAN HIEROGLYPH NU021;Lo;0;L;;;;;N;;;;;
+1324E;EGYPTIAN HIEROGLYPH NU022;Lo;0;L;;;;;N;;;;;
+1324F;EGYPTIAN HIEROGLYPH NU022A;Lo;0;L;;;;;N;;;;;
+13250;EGYPTIAN HIEROGLYPH O001;Lo;0;L;;;;;N;;;;;
+13251;EGYPTIAN HIEROGLYPH O001A;Lo;0;L;;;;;N;;;;;
+13252;EGYPTIAN HIEROGLYPH O002;Lo;0;L;;;;;N;;;;;
+13253;EGYPTIAN HIEROGLYPH O003;Lo;0;L;;;;;N;;;;;
+13254;EGYPTIAN HIEROGLYPH O004;Lo;0;L;;;;;N;;;;;
+13255;EGYPTIAN HIEROGLYPH O005;Lo;0;L;;;;;N;;;;;
+13256;EGYPTIAN HIEROGLYPH O005A;Lo;0;L;;;;;N;;;;;
+13257;EGYPTIAN HIEROGLYPH O006;Lo;0;L;;;;;N;;;;;
+13258;EGYPTIAN HIEROGLYPH O006A;Lo;0;L;;;;;N;;;;;
+13259;EGYPTIAN HIEROGLYPH O006B;Lo;0;L;;;;;N;;;;;
+1325A;EGYPTIAN HIEROGLYPH O006C;Lo;0;L;;;;;N;;;;;
+1325B;EGYPTIAN HIEROGLYPH O006D;Lo;0;L;;;;;N;;;;;
+1325C;EGYPTIAN HIEROGLYPH O006E;Lo;0;L;;;;;N;;;;;
+1325D;EGYPTIAN HIEROGLYPH O006F;Lo;0;L;;;;;N;;;;;
+1325E;EGYPTIAN HIEROGLYPH O007;Lo;0;L;;;;;N;;;;;
+1325F;EGYPTIAN HIEROGLYPH O008;Lo;0;L;;;;;N;;;;;
+13260;EGYPTIAN HIEROGLYPH O009;Lo;0;L;;;;;N;;;;;
+13261;EGYPTIAN HIEROGLYPH O010;Lo;0;L;;;;;N;;;;;
+13262;EGYPTIAN HIEROGLYPH O010A;Lo;0;L;;;;;N;;;;;
+13263;EGYPTIAN HIEROGLYPH O010B;Lo;0;L;;;;;N;;;;;
+13264;EGYPTIAN HIEROGLYPH O010C;Lo;0;L;;;;;N;;;;;
+13265;EGYPTIAN HIEROGLYPH O011;Lo;0;L;;;;;N;;;;;
+13266;EGYPTIAN HIEROGLYPH O012;Lo;0;L;;;;;N;;;;;
+13267;EGYPTIAN HIEROGLYPH O013;Lo;0;L;;;;;N;;;;;
+13268;EGYPTIAN HIEROGLYPH O014;Lo;0;L;;;;;N;;;;;
+13269;EGYPTIAN HIEROGLYPH O015;Lo;0;L;;;;;N;;;;;
+1326A;EGYPTIAN HIEROGLYPH O016;Lo;0;L;;;;;N;;;;;
+1326B;EGYPTIAN HIEROGLYPH O017;Lo;0;L;;;;;N;;;;;
+1326C;EGYPTIAN HIEROGLYPH O018;Lo;0;L;;;;;N;;;;;
+1326D;EGYPTIAN HIEROGLYPH O019;Lo;0;L;;;;;N;;;;;
+1326E;EGYPTIAN HIEROGLYPH O019A;Lo;0;L;;;;;N;;;;;
+1326F;EGYPTIAN HIEROGLYPH O020;Lo;0;L;;;;;N;;;;;
+13270;EGYPTIAN HIEROGLYPH O020A;Lo;0;L;;;;;N;;;;;
+13271;EGYPTIAN HIEROGLYPH O021;Lo;0;L;;;;;N;;;;;
+13272;EGYPTIAN HIEROGLYPH O022;Lo;0;L;;;;;N;;;;;
+13273;EGYPTIAN HIEROGLYPH O023;Lo;0;L;;;;;N;;;;;
+13274;EGYPTIAN HIEROGLYPH O024;Lo;0;L;;;;;N;;;;;
+13275;EGYPTIAN HIEROGLYPH O024A;Lo;0;L;;;;;N;;;;;
+13276;EGYPTIAN HIEROGLYPH O025;Lo;0;L;;;;;N;;;;;
+13277;EGYPTIAN HIEROGLYPH O025A;Lo;0;L;;;;;N;;;;;
+13278;EGYPTIAN HIEROGLYPH O026;Lo;0;L;;;;;N;;;;;
+13279;EGYPTIAN HIEROGLYPH O027;Lo;0;L;;;;;N;;;;;
+1327A;EGYPTIAN HIEROGLYPH O028;Lo;0;L;;;;;N;;;;;
+1327B;EGYPTIAN HIEROGLYPH O029;Lo;0;L;;;;;N;;;;;
+1327C;EGYPTIAN HIEROGLYPH O029A;Lo;0;L;;;;;N;;;;;
+1327D;EGYPTIAN HIEROGLYPH O030;Lo;0;L;;;;;N;;;;;
+1327E;EGYPTIAN HIEROGLYPH O030A;Lo;0;L;;;;;N;;;;;
+1327F;EGYPTIAN HIEROGLYPH O031;Lo;0;L;;;;;N;;;;;
+13280;EGYPTIAN HIEROGLYPH O032;Lo;0;L;;;;;N;;;;;
+13281;EGYPTIAN HIEROGLYPH O033;Lo;0;L;;;;;N;;;;;
+13282;EGYPTIAN HIEROGLYPH O033A;Lo;0;L;;;;;N;;;;;
+13283;EGYPTIAN HIEROGLYPH O034;Lo;0;L;;;;;N;;;;;
+13284;EGYPTIAN HIEROGLYPH O035;Lo;0;L;;;;;N;;;;;
+13285;EGYPTIAN HIEROGLYPH O036;Lo;0;L;;;;;N;;;;;
+13286;EGYPTIAN HIEROGLYPH O036A;Lo;0;L;;;;;N;;;;;
+13287;EGYPTIAN HIEROGLYPH O036B;Lo;0;L;;;;;N;;;;;
+13288;EGYPTIAN HIEROGLYPH O036C;Lo;0;L;;;;;N;;;;;
+13289;EGYPTIAN HIEROGLYPH O036D;Lo;0;L;;;;;N;;;;;
+1328A;EGYPTIAN HIEROGLYPH O037;Lo;0;L;;;;;N;;;;;
+1328B;EGYPTIAN HIEROGLYPH O038;Lo;0;L;;;;;N;;;;;
+1328C;EGYPTIAN HIEROGLYPH O039;Lo;0;L;;;;;N;;;;;
+1328D;EGYPTIAN HIEROGLYPH O040;Lo;0;L;;;;;N;;;;;
+1328E;EGYPTIAN HIEROGLYPH O041;Lo;0;L;;;;;N;;;;;
+1328F;EGYPTIAN HIEROGLYPH O042;Lo;0;L;;;;;N;;;;;
+13290;EGYPTIAN HIEROGLYPH O043;Lo;0;L;;;;;N;;;;;
+13291;EGYPTIAN HIEROGLYPH O044;Lo;0;L;;;;;N;;;;;
+13292;EGYPTIAN HIEROGLYPH O045;Lo;0;L;;;;;N;;;;;
+13293;EGYPTIAN HIEROGLYPH O046;Lo;0;L;;;;;N;;;;;
+13294;EGYPTIAN HIEROGLYPH O047;Lo;0;L;;;;;N;;;;;
+13295;EGYPTIAN HIEROGLYPH O048;Lo;0;L;;;;;N;;;;;
+13296;EGYPTIAN HIEROGLYPH O049;Lo;0;L;;;;;N;;;;;
+13297;EGYPTIAN HIEROGLYPH O050;Lo;0;L;;;;;N;;;;;
+13298;EGYPTIAN HIEROGLYPH O050A;Lo;0;L;;;;;N;;;;;
+13299;EGYPTIAN HIEROGLYPH O050B;Lo;0;L;;;;;N;;;;;
+1329A;EGYPTIAN HIEROGLYPH O051;Lo;0;L;;;;;N;;;;;
+1329B;EGYPTIAN HIEROGLYPH P001;Lo;0;L;;;;;N;;;;;
+1329C;EGYPTIAN HIEROGLYPH P001A;Lo;0;L;;;;;N;;;;;
+1329D;EGYPTIAN HIEROGLYPH P002;Lo;0;L;;;;;N;;;;;
+1329E;EGYPTIAN HIEROGLYPH P003;Lo;0;L;;;;;N;;;;;
+1329F;EGYPTIAN HIEROGLYPH P003A;Lo;0;L;;;;;N;;;;;
+132A0;EGYPTIAN HIEROGLYPH P004;Lo;0;L;;;;;N;;;;;
+132A1;EGYPTIAN HIEROGLYPH P005;Lo;0;L;;;;;N;;;;;
+132A2;EGYPTIAN HIEROGLYPH P006;Lo;0;L;;;;;N;;;;;
+132A3;EGYPTIAN HIEROGLYPH P007;Lo;0;L;;;;;N;;;;;
+132A4;EGYPTIAN HIEROGLYPH P008;Lo;0;L;;;;;N;;;;;
+132A5;EGYPTIAN HIEROGLYPH P009;Lo;0;L;;;;;N;;;;;
+132A6;EGYPTIAN HIEROGLYPH P010;Lo;0;L;;;;;N;;;;;
+132A7;EGYPTIAN HIEROGLYPH P011;Lo;0;L;;;;;N;;;;;
+132A8;EGYPTIAN HIEROGLYPH Q001;Lo;0;L;;;;;N;;;;;
+132A9;EGYPTIAN HIEROGLYPH Q002;Lo;0;L;;;;;N;;;;;
+132AA;EGYPTIAN HIEROGLYPH Q003;Lo;0;L;;;;;N;;;;;
+132AB;EGYPTIAN HIEROGLYPH Q004;Lo;0;L;;;;;N;;;;;
+132AC;EGYPTIAN HIEROGLYPH Q005;Lo;0;L;;;;;N;;;;;
+132AD;EGYPTIAN HIEROGLYPH Q006;Lo;0;L;;;;;N;;;;;
+132AE;EGYPTIAN HIEROGLYPH Q007;Lo;0;L;;;;;N;;;;;
+132AF;EGYPTIAN HIEROGLYPH R001;Lo;0;L;;;;;N;;;;;
+132B0;EGYPTIAN HIEROGLYPH R002;Lo;0;L;;;;;N;;;;;
+132B1;EGYPTIAN HIEROGLYPH R002A;Lo;0;L;;;;;N;;;;;
+132B2;EGYPTIAN HIEROGLYPH R003;Lo;0;L;;;;;N;;;;;
+132B3;EGYPTIAN HIEROGLYPH R003A;Lo;0;L;;;;;N;;;;;
+132B4;EGYPTIAN HIEROGLYPH R003B;Lo;0;L;;;;;N;;;;;
+132B5;EGYPTIAN HIEROGLYPH R004;Lo;0;L;;;;;N;;;;;
+132B6;EGYPTIAN HIEROGLYPH R005;Lo;0;L;;;;;N;;;;;
+132B7;EGYPTIAN HIEROGLYPH R006;Lo;0;L;;;;;N;;;;;
+132B8;EGYPTIAN HIEROGLYPH R007;Lo;0;L;;;;;N;;;;;
+132B9;EGYPTIAN HIEROGLYPH R008;Lo;0;L;;;;;N;;;;;
+132BA;EGYPTIAN HIEROGLYPH R009;Lo;0;L;;;;;N;;;;;
+132BB;EGYPTIAN HIEROGLYPH R010;Lo;0;L;;;;;N;;;;;
+132BC;EGYPTIAN HIEROGLYPH R010A;Lo;0;L;;;;;N;;;;;
+132BD;EGYPTIAN HIEROGLYPH R011;Lo;0;L;;;;;N;;;;;
+132BE;EGYPTIAN HIEROGLYPH R012;Lo;0;L;;;;;N;;;;;
+132BF;EGYPTIAN HIEROGLYPH R013;Lo;0;L;;;;;N;;;;;
+132C0;EGYPTIAN HIEROGLYPH R014;Lo;0;L;;;;;N;;;;;
+132C1;EGYPTIAN HIEROGLYPH R015;Lo;0;L;;;;;N;;;;;
+132C2;EGYPTIAN HIEROGLYPH R016;Lo;0;L;;;;;N;;;;;
+132C3;EGYPTIAN HIEROGLYPH R016A;Lo;0;L;;;;;N;;;;;
+132C4;EGYPTIAN HIEROGLYPH R017;Lo;0;L;;;;;N;;;;;
+132C5;EGYPTIAN HIEROGLYPH R018;Lo;0;L;;;;;N;;;;;
+132C6;EGYPTIAN HIEROGLYPH R019;Lo;0;L;;;;;N;;;;;
+132C7;EGYPTIAN HIEROGLYPH R020;Lo;0;L;;;;;N;;;;;
+132C8;EGYPTIAN HIEROGLYPH R021;Lo;0;L;;;;;N;;;;;
+132C9;EGYPTIAN HIEROGLYPH R022;Lo;0;L;;;;;N;;;;;
+132CA;EGYPTIAN HIEROGLYPH R023;Lo;0;L;;;;;N;;;;;
+132CB;EGYPTIAN HIEROGLYPH R024;Lo;0;L;;;;;N;;;;;
+132CC;EGYPTIAN HIEROGLYPH R025;Lo;0;L;;;;;N;;;;;
+132CD;EGYPTIAN HIEROGLYPH R026;Lo;0;L;;;;;N;;;;;
+132CE;EGYPTIAN HIEROGLYPH R027;Lo;0;L;;;;;N;;;;;
+132CF;EGYPTIAN HIEROGLYPH R028;Lo;0;L;;;;;N;;;;;
+132D0;EGYPTIAN HIEROGLYPH R029;Lo;0;L;;;;;N;;;;;
+132D1;EGYPTIAN HIEROGLYPH S001;Lo;0;L;;;;;N;;;;;
+132D2;EGYPTIAN HIEROGLYPH S002;Lo;0;L;;;;;N;;;;;
+132D3;EGYPTIAN HIEROGLYPH S002A;Lo;0;L;;;;;N;;;;;
+132D4;EGYPTIAN HIEROGLYPH S003;Lo;0;L;;;;;N;;;;;
+132D5;EGYPTIAN HIEROGLYPH S004;Lo;0;L;;;;;N;;;;;
+132D6;EGYPTIAN HIEROGLYPH S005;Lo;0;L;;;;;N;;;;;
+132D7;EGYPTIAN HIEROGLYPH S006;Lo;0;L;;;;;N;;;;;
+132D8;EGYPTIAN HIEROGLYPH S006A;Lo;0;L;;;;;N;;;;;
+132D9;EGYPTIAN HIEROGLYPH S007;Lo;0;L;;;;;N;;;;;
+132DA;EGYPTIAN HIEROGLYPH S008;Lo;0;L;;;;;N;;;;;
+132DB;EGYPTIAN HIEROGLYPH S009;Lo;0;L;;;;;N;;;;;
+132DC;EGYPTIAN HIEROGLYPH S010;Lo;0;L;;;;;N;;;;;
+132DD;EGYPTIAN HIEROGLYPH S011;Lo;0;L;;;;;N;;;;;
+132DE;EGYPTIAN HIEROGLYPH S012;Lo;0;L;;;;;N;;;;;
+132DF;EGYPTIAN HIEROGLYPH S013;Lo;0;L;;;;;N;;;;;
+132E0;EGYPTIAN HIEROGLYPH S014;Lo;0;L;;;;;N;;;;;
+132E1;EGYPTIAN HIEROGLYPH S014A;Lo;0;L;;;;;N;;;;;
+132E2;EGYPTIAN HIEROGLYPH S014B;Lo;0;L;;;;;N;;;;;
+132E3;EGYPTIAN HIEROGLYPH S015;Lo;0;L;;;;;N;;;;;
+132E4;EGYPTIAN HIEROGLYPH S016;Lo;0;L;;;;;N;;;;;
+132E5;EGYPTIAN HIEROGLYPH S017;Lo;0;L;;;;;N;;;;;
+132E6;EGYPTIAN HIEROGLYPH S017A;Lo;0;L;;;;;N;;;;;
+132E7;EGYPTIAN HIEROGLYPH S018;Lo;0;L;;;;;N;;;;;
+132E8;EGYPTIAN HIEROGLYPH S019;Lo;0;L;;;;;N;;;;;
+132E9;EGYPTIAN HIEROGLYPH S020;Lo;0;L;;;;;N;;;;;
+132EA;EGYPTIAN HIEROGLYPH S021;Lo;0;L;;;;;N;;;;;
+132EB;EGYPTIAN HIEROGLYPH S022;Lo;0;L;;;;;N;;;;;
+132EC;EGYPTIAN HIEROGLYPH S023;Lo;0;L;;;;;N;;;;;
+132ED;EGYPTIAN HIEROGLYPH S024;Lo;0;L;;;;;N;;;;;
+132EE;EGYPTIAN HIEROGLYPH S025;Lo;0;L;;;;;N;;;;;
+132EF;EGYPTIAN HIEROGLYPH S026;Lo;0;L;;;;;N;;;;;
+132F0;EGYPTIAN HIEROGLYPH S026A;Lo;0;L;;;;;N;;;;;
+132F1;EGYPTIAN HIEROGLYPH S026B;Lo;0;L;;;;;N;;;;;
+132F2;EGYPTIAN HIEROGLYPH S027;Lo;0;L;;;;;N;;;;;
+132F3;EGYPTIAN HIEROGLYPH S028;Lo;0;L;;;;;N;;;;;
+132F4;EGYPTIAN HIEROGLYPH S029;Lo;0;L;;;;;N;;;;;
+132F5;EGYPTIAN HIEROGLYPH S030;Lo;0;L;;;;;N;;;;;
+132F6;EGYPTIAN HIEROGLYPH S031;Lo;0;L;;;;;N;;;;;
+132F7;EGYPTIAN HIEROGLYPH S032;Lo;0;L;;;;;N;;;;;
+132F8;EGYPTIAN HIEROGLYPH S033;Lo;0;L;;;;;N;;;;;
+132F9;EGYPTIAN HIEROGLYPH S034;Lo;0;L;;;;;N;;;;;
+132FA;EGYPTIAN HIEROGLYPH S035;Lo;0;L;;;;;N;;;;;
+132FB;EGYPTIAN HIEROGLYPH S035A;Lo;0;L;;;;;N;;;;;
+132FC;EGYPTIAN HIEROGLYPH S036;Lo;0;L;;;;;N;;;;;
+132FD;EGYPTIAN HIEROGLYPH S037;Lo;0;L;;;;;N;;;;;
+132FE;EGYPTIAN HIEROGLYPH S038;Lo;0;L;;;;;N;;;;;
+132FF;EGYPTIAN HIEROGLYPH S039;Lo;0;L;;;;;N;;;;;
+13300;EGYPTIAN HIEROGLYPH S040;Lo;0;L;;;;;N;;;;;
+13301;EGYPTIAN HIEROGLYPH S041;Lo;0;L;;;;;N;;;;;
+13302;EGYPTIAN HIEROGLYPH S042;Lo;0;L;;;;;N;;;;;
+13303;EGYPTIAN HIEROGLYPH S043;Lo;0;L;;;;;N;;;;;
+13304;EGYPTIAN HIEROGLYPH S044;Lo;0;L;;;;;N;;;;;
+13305;EGYPTIAN HIEROGLYPH S045;Lo;0;L;;;;;N;;;;;
+13306;EGYPTIAN HIEROGLYPH S046;Lo;0;L;;;;;N;;;;;
+13307;EGYPTIAN HIEROGLYPH T001;Lo;0;L;;;;;N;;;;;
+13308;EGYPTIAN HIEROGLYPH T002;Lo;0;L;;;;;N;;;;;
+13309;EGYPTIAN HIEROGLYPH T003;Lo;0;L;;;;;N;;;;;
+1330A;EGYPTIAN HIEROGLYPH T003A;Lo;0;L;;;;;N;;;;;
+1330B;EGYPTIAN HIEROGLYPH T004;Lo;0;L;;;;;N;;;;;
+1330C;EGYPTIAN HIEROGLYPH T005;Lo;0;L;;;;;N;;;;;
+1330D;EGYPTIAN HIEROGLYPH T006;Lo;0;L;;;;;N;;;;;
+1330E;EGYPTIAN HIEROGLYPH T007;Lo;0;L;;;;;N;;;;;
+1330F;EGYPTIAN HIEROGLYPH T007A;Lo;0;L;;;;;N;;;;;
+13310;EGYPTIAN HIEROGLYPH T008;Lo;0;L;;;;;N;;;;;
+13311;EGYPTIAN HIEROGLYPH T008A;Lo;0;L;;;;;N;;;;;
+13312;EGYPTIAN HIEROGLYPH T009;Lo;0;L;;;;;N;;;;;
+13313;EGYPTIAN HIEROGLYPH T009A;Lo;0;L;;;;;N;;;;;
+13314;EGYPTIAN HIEROGLYPH T010;Lo;0;L;;;;;N;;;;;
+13315;EGYPTIAN HIEROGLYPH T011;Lo;0;L;;;;;N;;;;;
+13316;EGYPTIAN HIEROGLYPH T011A;Lo;0;L;;;;;N;;;;;
+13317;EGYPTIAN HIEROGLYPH T012;Lo;0;L;;;;;N;;;;;
+13318;EGYPTIAN HIEROGLYPH T013;Lo;0;L;;;;;N;;;;;
+13319;EGYPTIAN HIEROGLYPH T014;Lo;0;L;;;;;N;;;;;
+1331A;EGYPTIAN HIEROGLYPH T015;Lo;0;L;;;;;N;;;;;
+1331B;EGYPTIAN HIEROGLYPH T016;Lo;0;L;;;;;N;;;;;
+1331C;EGYPTIAN HIEROGLYPH T016A;Lo;0;L;;;;;N;;;;;
+1331D;EGYPTIAN HIEROGLYPH T017;Lo;0;L;;;;;N;;;;;
+1331E;EGYPTIAN HIEROGLYPH T018;Lo;0;L;;;;;N;;;;;
+1331F;EGYPTIAN HIEROGLYPH T019;Lo;0;L;;;;;N;;;;;
+13320;EGYPTIAN HIEROGLYPH T020;Lo;0;L;;;;;N;;;;;
+13321;EGYPTIAN HIEROGLYPH T021;Lo;0;L;;;;;N;;;;;
+13322;EGYPTIAN HIEROGLYPH T022;Lo;0;L;;;;;N;;;;;
+13323;EGYPTIAN HIEROGLYPH T023;Lo;0;L;;;;;N;;;;;
+13324;EGYPTIAN HIEROGLYPH T024;Lo;0;L;;;;;N;;;;;
+13325;EGYPTIAN HIEROGLYPH T025;Lo;0;L;;;;;N;;;;;
+13326;EGYPTIAN HIEROGLYPH T026;Lo;0;L;;;;;N;;;;;
+13327;EGYPTIAN HIEROGLYPH T027;Lo;0;L;;;;;N;;;;;
+13328;EGYPTIAN HIEROGLYPH T028;Lo;0;L;;;;;N;;;;;
+13329;EGYPTIAN HIEROGLYPH T029;Lo;0;L;;;;;N;;;;;
+1332A;EGYPTIAN HIEROGLYPH T030;Lo;0;L;;;;;N;;;;;
+1332B;EGYPTIAN HIEROGLYPH T031;Lo;0;L;;;;;N;;;;;
+1332C;EGYPTIAN HIEROGLYPH T032;Lo;0;L;;;;;N;;;;;
+1332D;EGYPTIAN HIEROGLYPH T032A;Lo;0;L;;;;;N;;;;;
+1332E;EGYPTIAN HIEROGLYPH T033;Lo;0;L;;;;;N;;;;;
+1332F;EGYPTIAN HIEROGLYPH T033A;Lo;0;L;;;;;N;;;;;
+13330;EGYPTIAN HIEROGLYPH T034;Lo;0;L;;;;;N;;;;;
+13331;EGYPTIAN HIEROGLYPH T035;Lo;0;L;;;;;N;;;;;
+13332;EGYPTIAN HIEROGLYPH T036;Lo;0;L;;;;;N;;;;;
+13333;EGYPTIAN HIEROGLYPH U001;Lo;0;L;;;;;N;;;;;
+13334;EGYPTIAN HIEROGLYPH U002;Lo;0;L;;;;;N;;;;;
+13335;EGYPTIAN HIEROGLYPH U003;Lo;0;L;;;;;N;;;;;
+13336;EGYPTIAN HIEROGLYPH U004;Lo;0;L;;;;;N;;;;;
+13337;EGYPTIAN HIEROGLYPH U005;Lo;0;L;;;;;N;;;;;
+13338;EGYPTIAN HIEROGLYPH U006;Lo;0;L;;;;;N;;;;;
+13339;EGYPTIAN HIEROGLYPH U006A;Lo;0;L;;;;;N;;;;;
+1333A;EGYPTIAN HIEROGLYPH U006B;Lo;0;L;;;;;N;;;;;
+1333B;EGYPTIAN HIEROGLYPH U007;Lo;0;L;;;;;N;;;;;
+1333C;EGYPTIAN HIEROGLYPH U008;Lo;0;L;;;;;N;;;;;
+1333D;EGYPTIAN HIEROGLYPH U009;Lo;0;L;;;;;N;;;;;
+1333E;EGYPTIAN HIEROGLYPH U010;Lo;0;L;;;;;N;;;;;
+1333F;EGYPTIAN HIEROGLYPH U011;Lo;0;L;;;;;N;;;;;
+13340;EGYPTIAN HIEROGLYPH U012;Lo;0;L;;;;;N;;;;;
+13341;EGYPTIAN HIEROGLYPH U013;Lo;0;L;;;;;N;;;;;
+13342;EGYPTIAN HIEROGLYPH U014;Lo;0;L;;;;;N;;;;;
+13343;EGYPTIAN HIEROGLYPH U015;Lo;0;L;;;;;N;;;;;
+13344;EGYPTIAN HIEROGLYPH U016;Lo;0;L;;;;;N;;;;;
+13345;EGYPTIAN HIEROGLYPH U017;Lo;0;L;;;;;N;;;;;
+13346;EGYPTIAN HIEROGLYPH U018;Lo;0;L;;;;;N;;;;;
+13347;EGYPTIAN HIEROGLYPH U019;Lo;0;L;;;;;N;;;;;
+13348;EGYPTIAN HIEROGLYPH U020;Lo;0;L;;;;;N;;;;;
+13349;EGYPTIAN HIEROGLYPH U021;Lo;0;L;;;;;N;;;;;
+1334A;EGYPTIAN HIEROGLYPH U022;Lo;0;L;;;;;N;;;;;
+1334B;EGYPTIAN HIEROGLYPH U023;Lo;0;L;;;;;N;;;;;
+1334C;EGYPTIAN HIEROGLYPH U023A;Lo;0;L;;;;;N;;;;;
+1334D;EGYPTIAN HIEROGLYPH U024;Lo;0;L;;;;;N;;;;;
+1334E;EGYPTIAN HIEROGLYPH U025;Lo;0;L;;;;;N;;;;;
+1334F;EGYPTIAN HIEROGLYPH U026;Lo;0;L;;;;;N;;;;;
+13350;EGYPTIAN HIEROGLYPH U027;Lo;0;L;;;;;N;;;;;
+13351;EGYPTIAN HIEROGLYPH U028;Lo;0;L;;;;;N;;;;;
+13352;EGYPTIAN HIEROGLYPH U029;Lo;0;L;;;;;N;;;;;
+13353;EGYPTIAN HIEROGLYPH U029A;Lo;0;L;;;;;N;;;;;
+13354;EGYPTIAN HIEROGLYPH U030;Lo;0;L;;;;;N;;;;;
+13355;EGYPTIAN HIEROGLYPH U031;Lo;0;L;;;;;N;;;;;
+13356;EGYPTIAN HIEROGLYPH U032;Lo;0;L;;;;;N;;;;;
+13357;EGYPTIAN HIEROGLYPH U032A;Lo;0;L;;;;;N;;;;;
+13358;EGYPTIAN HIEROGLYPH U033;Lo;0;L;;;;;N;;;;;
+13359;EGYPTIAN HIEROGLYPH U034;Lo;0;L;;;;;N;;;;;
+1335A;EGYPTIAN HIEROGLYPH U035;Lo;0;L;;;;;N;;;;;
+1335B;EGYPTIAN HIEROGLYPH U036;Lo;0;L;;;;;N;;;;;
+1335C;EGYPTIAN HIEROGLYPH U037;Lo;0;L;;;;;N;;;;;
+1335D;EGYPTIAN HIEROGLYPH U038;Lo;0;L;;;;;N;;;;;
+1335E;EGYPTIAN HIEROGLYPH U039;Lo;0;L;;;;;N;;;;;
+1335F;EGYPTIAN HIEROGLYPH U040;Lo;0;L;;;;;N;;;;;
+13360;EGYPTIAN HIEROGLYPH U041;Lo;0;L;;;;;N;;;;;
+13361;EGYPTIAN HIEROGLYPH U042;Lo;0;L;;;;;N;;;;;
+13362;EGYPTIAN HIEROGLYPH V001;Lo;0;L;;;;;N;;;;;
+13363;EGYPTIAN HIEROGLYPH V001A;Lo;0;L;;;;;N;;;;;
+13364;EGYPTIAN HIEROGLYPH V001B;Lo;0;L;;;;;N;;;;;
+13365;EGYPTIAN HIEROGLYPH V001C;Lo;0;L;;;;;N;;;;;
+13366;EGYPTIAN HIEROGLYPH V001D;Lo;0;L;;;;;N;;;;;
+13367;EGYPTIAN HIEROGLYPH V001E;Lo;0;L;;;;;N;;;;;
+13368;EGYPTIAN HIEROGLYPH V001F;Lo;0;L;;;;;N;;;;;
+13369;EGYPTIAN HIEROGLYPH V001G;Lo;0;L;;;;;N;;;;;
+1336A;EGYPTIAN HIEROGLYPH V001H;Lo;0;L;;;;;N;;;;;
+1336B;EGYPTIAN HIEROGLYPH V001I;Lo;0;L;;;;;N;;;;;
+1336C;EGYPTIAN HIEROGLYPH V002;Lo;0;L;;;;;N;;;;;
+1336D;EGYPTIAN HIEROGLYPH V002A;Lo;0;L;;;;;N;;;;;
+1336E;EGYPTIAN HIEROGLYPH V003;Lo;0;L;;;;;N;;;;;
+1336F;EGYPTIAN HIEROGLYPH V004;Lo;0;L;;;;;N;;;;;
+13370;EGYPTIAN HIEROGLYPH V005;Lo;0;L;;;;;N;;;;;
+13371;EGYPTIAN HIEROGLYPH V006;Lo;0;L;;;;;N;;;;;
+13372;EGYPTIAN HIEROGLYPH V007;Lo;0;L;;;;;N;;;;;
+13373;EGYPTIAN HIEROGLYPH V007A;Lo;0;L;;;;;N;;;;;
+13374;EGYPTIAN HIEROGLYPH V007B;Lo;0;L;;;;;N;;;;;
+13375;EGYPTIAN HIEROGLYPH V008;Lo;0;L;;;;;N;;;;;
+13376;EGYPTIAN HIEROGLYPH V009;Lo;0;L;;;;;N;;;;;
+13377;EGYPTIAN HIEROGLYPH V010;Lo;0;L;;;;;N;;;;;
+13378;EGYPTIAN HIEROGLYPH V011;Lo;0;L;;;;;N;;;;;
+13379;EGYPTIAN HIEROGLYPH V011A;Lo;0;L;;;;;N;;;;;
+1337A;EGYPTIAN HIEROGLYPH V011B;Lo;0;L;;;;;N;;;;;
+1337B;EGYPTIAN HIEROGLYPH V011C;Lo;0;L;;;;;N;;;;;
+1337C;EGYPTIAN HIEROGLYPH V012;Lo;0;L;;;;;N;;;;;
+1337D;EGYPTIAN HIEROGLYPH V012A;Lo;0;L;;;;;N;;;;;
+1337E;EGYPTIAN HIEROGLYPH V012B;Lo;0;L;;;;;N;;;;;
+1337F;EGYPTIAN HIEROGLYPH V013;Lo;0;L;;;;;N;;;;;
+13380;EGYPTIAN HIEROGLYPH V014;Lo;0;L;;;;;N;;;;;
+13381;EGYPTIAN HIEROGLYPH V015;Lo;0;L;;;;;N;;;;;
+13382;EGYPTIAN HIEROGLYPH V016;Lo;0;L;;;;;N;;;;;
+13383;EGYPTIAN HIEROGLYPH V017;Lo;0;L;;;;;N;;;;;
+13384;EGYPTIAN HIEROGLYPH V018;Lo;0;L;;;;;N;;;;;
+13385;EGYPTIAN HIEROGLYPH V019;Lo;0;L;;;;;N;;;;;
+13386;EGYPTIAN HIEROGLYPH V020;Lo;0;L;;;;;N;;;;;
+13387;EGYPTIAN HIEROGLYPH V020A;Lo;0;L;;;;;N;;;;;
+13388;EGYPTIAN HIEROGLYPH V020B;Lo;0;L;;;;;N;;;;;
+13389;EGYPTIAN HIEROGLYPH V020C;Lo;0;L;;;;;N;;;;;
+1338A;EGYPTIAN HIEROGLYPH V020D;Lo;0;L;;;;;N;;;;;
+1338B;EGYPTIAN HIEROGLYPH V020E;Lo;0;L;;;;;N;;;;;
+1338C;EGYPTIAN HIEROGLYPH V020F;Lo;0;L;;;;;N;;;;;
+1338D;EGYPTIAN HIEROGLYPH V020G;Lo;0;L;;;;;N;;;;;
+1338E;EGYPTIAN HIEROGLYPH V020H;Lo;0;L;;;;;N;;;;;
+1338F;EGYPTIAN HIEROGLYPH V020I;Lo;0;L;;;;;N;;;;;
+13390;EGYPTIAN HIEROGLYPH V020J;Lo;0;L;;;;;N;;;;;
+13391;EGYPTIAN HIEROGLYPH V020K;Lo;0;L;;;;;N;;;;;
+13392;EGYPTIAN HIEROGLYPH V020L;Lo;0;L;;;;;N;;;;;
+13393;EGYPTIAN HIEROGLYPH V021;Lo;0;L;;;;;N;;;;;
+13394;EGYPTIAN HIEROGLYPH V022;Lo;0;L;;;;;N;;;;;
+13395;EGYPTIAN HIEROGLYPH V023;Lo;0;L;;;;;N;;;;;
+13396;EGYPTIAN HIEROGLYPH V023A;Lo;0;L;;;;;N;;;;;
+13397;EGYPTIAN HIEROGLYPH V024;Lo;0;L;;;;;N;;;;;
+13398;EGYPTIAN HIEROGLYPH V025;Lo;0;L;;;;;N;;;;;
+13399;EGYPTIAN HIEROGLYPH V026;Lo;0;L;;;;;N;;;;;
+1339A;EGYPTIAN HIEROGLYPH V027;Lo;0;L;;;;;N;;;;;
+1339B;EGYPTIAN HIEROGLYPH V028;Lo;0;L;;;;;N;;;;;
+1339C;EGYPTIAN HIEROGLYPH V028A;Lo;0;L;;;;;N;;;;;
+1339D;EGYPTIAN HIEROGLYPH V029;Lo;0;L;;;;;N;;;;;
+1339E;EGYPTIAN HIEROGLYPH V029A;Lo;0;L;;;;;N;;;;;
+1339F;EGYPTIAN HIEROGLYPH V030;Lo;0;L;;;;;N;;;;;
+133A0;EGYPTIAN HIEROGLYPH V030A;Lo;0;L;;;;;N;;;;;
+133A1;EGYPTIAN HIEROGLYPH V031;Lo;0;L;;;;;N;;;;;
+133A2;EGYPTIAN HIEROGLYPH V031A;Lo;0;L;;;;;N;;;;;
+133A3;EGYPTIAN HIEROGLYPH V032;Lo;0;L;;;;;N;;;;;
+133A4;EGYPTIAN HIEROGLYPH V033;Lo;0;L;;;;;N;;;;;
+133A5;EGYPTIAN HIEROGLYPH V033A;Lo;0;L;;;;;N;;;;;
+133A6;EGYPTIAN HIEROGLYPH V034;Lo;0;L;;;;;N;;;;;
+133A7;EGYPTIAN HIEROGLYPH V035;Lo;0;L;;;;;N;;;;;
+133A8;EGYPTIAN HIEROGLYPH V036;Lo;0;L;;;;;N;;;;;
+133A9;EGYPTIAN HIEROGLYPH V037;Lo;0;L;;;;;N;;;;;
+133AA;EGYPTIAN HIEROGLYPH V037A;Lo;0;L;;;;;N;;;;;
+133AB;EGYPTIAN HIEROGLYPH V038;Lo;0;L;;;;;N;;;;;
+133AC;EGYPTIAN HIEROGLYPH V039;Lo;0;L;;;;;N;;;;;
+133AD;EGYPTIAN HIEROGLYPH V040;Lo;0;L;;;;;N;;;;;
+133AE;EGYPTIAN HIEROGLYPH V040A;Lo;0;L;;;;;N;;;;;
+133AF;EGYPTIAN HIEROGLYPH W001;Lo;0;L;;;;;N;;;;;
+133B0;EGYPTIAN HIEROGLYPH W002;Lo;0;L;;;;;N;;;;;
+133B1;EGYPTIAN HIEROGLYPH W003;Lo;0;L;;;;;N;;;;;
+133B2;EGYPTIAN HIEROGLYPH W003A;Lo;0;L;;;;;N;;;;;
+133B3;EGYPTIAN HIEROGLYPH W004;Lo;0;L;;;;;N;;;;;
+133B4;EGYPTIAN HIEROGLYPH W005;Lo;0;L;;;;;N;;;;;
+133B5;EGYPTIAN HIEROGLYPH W006;Lo;0;L;;;;;N;;;;;
+133B6;EGYPTIAN HIEROGLYPH W007;Lo;0;L;;;;;N;;;;;
+133B7;EGYPTIAN HIEROGLYPH W008;Lo;0;L;;;;;N;;;;;
+133B8;EGYPTIAN HIEROGLYPH W009;Lo;0;L;;;;;N;;;;;
+133B9;EGYPTIAN HIEROGLYPH W009A;Lo;0;L;;;;;N;;;;;
+133BA;EGYPTIAN HIEROGLYPH W010;Lo;0;L;;;;;N;;;;;
+133BB;EGYPTIAN HIEROGLYPH W010A;Lo;0;L;;;;;N;;;;;
+133BC;EGYPTIAN HIEROGLYPH W011;Lo;0;L;;;;;N;;;;;
+133BD;EGYPTIAN HIEROGLYPH W012;Lo;0;L;;;;;N;;;;;
+133BE;EGYPTIAN HIEROGLYPH W013;Lo;0;L;;;;;N;;;;;
+133BF;EGYPTIAN HIEROGLYPH W014;Lo;0;L;;;;;N;;;;;
+133C0;EGYPTIAN HIEROGLYPH W014A;Lo;0;L;;;;;N;;;;;
+133C1;EGYPTIAN HIEROGLYPH W015;Lo;0;L;;;;;N;;;;;
+133C2;EGYPTIAN HIEROGLYPH W016;Lo;0;L;;;;;N;;;;;
+133C3;EGYPTIAN HIEROGLYPH W017;Lo;0;L;;;;;N;;;;;
+133C4;EGYPTIAN HIEROGLYPH W017A;Lo;0;L;;;;;N;;;;;
+133C5;EGYPTIAN HIEROGLYPH W018;Lo;0;L;;;;;N;;;;;
+133C6;EGYPTIAN HIEROGLYPH W018A;Lo;0;L;;;;;N;;;;;
+133C7;EGYPTIAN HIEROGLYPH W019;Lo;0;L;;;;;N;;;;;
+133C8;EGYPTIAN HIEROGLYPH W020;Lo;0;L;;;;;N;;;;;
+133C9;EGYPTIAN HIEROGLYPH W021;Lo;0;L;;;;;N;;;;;
+133CA;EGYPTIAN HIEROGLYPH W022;Lo;0;L;;;;;N;;;;;
+133CB;EGYPTIAN HIEROGLYPH W023;Lo;0;L;;;;;N;;;;;
+133CC;EGYPTIAN HIEROGLYPH W024;Lo;0;L;;;;;N;;;;;
+133CD;EGYPTIAN HIEROGLYPH W024A;Lo;0;L;;;;;N;;;;;
+133CE;EGYPTIAN HIEROGLYPH W025;Lo;0;L;;;;;N;;;;;
+133CF;EGYPTIAN HIEROGLYPH X001;Lo;0;L;;;;;N;;;;;
+133D0;EGYPTIAN HIEROGLYPH X002;Lo;0;L;;;;;N;;;;;
+133D1;EGYPTIAN HIEROGLYPH X003;Lo;0;L;;;;;N;;;;;
+133D2;EGYPTIAN HIEROGLYPH X004;Lo;0;L;;;;;N;;;;;
+133D3;EGYPTIAN HIEROGLYPH X004A;Lo;0;L;;;;;N;;;;;
+133D4;EGYPTIAN HIEROGLYPH X004B;Lo;0;L;;;;;N;;;;;
+133D5;EGYPTIAN HIEROGLYPH X005;Lo;0;L;;;;;N;;;;;
+133D6;EGYPTIAN HIEROGLYPH X006;Lo;0;L;;;;;N;;;;;
+133D7;EGYPTIAN HIEROGLYPH X006A;Lo;0;L;;;;;N;;;;;
+133D8;EGYPTIAN HIEROGLYPH X007;Lo;0;L;;;;;N;;;;;
+133D9;EGYPTIAN HIEROGLYPH X008;Lo;0;L;;;;;N;;;;;
+133DA;EGYPTIAN HIEROGLYPH X008A;Lo;0;L;;;;;N;;;;;
+133DB;EGYPTIAN HIEROGLYPH Y001;Lo;0;L;;;;;N;;;;;
+133DC;EGYPTIAN HIEROGLYPH Y001A;Lo;0;L;;;;;N;;;;;
+133DD;EGYPTIAN HIEROGLYPH Y002;Lo;0;L;;;;;N;;;;;
+133DE;EGYPTIAN HIEROGLYPH Y003;Lo;0;L;;;;;N;;;;;
+133DF;EGYPTIAN HIEROGLYPH Y004;Lo;0;L;;;;;N;;;;;
+133E0;EGYPTIAN HIEROGLYPH Y005;Lo;0;L;;;;;N;;;;;
+133E1;EGYPTIAN HIEROGLYPH Y006;Lo;0;L;;;;;N;;;;;
+133E2;EGYPTIAN HIEROGLYPH Y007;Lo;0;L;;;;;N;;;;;
+133E3;EGYPTIAN HIEROGLYPH Y008;Lo;0;L;;;;;N;;;;;
+133E4;EGYPTIAN HIEROGLYPH Z001;Lo;0;L;;;;;N;;;;;
+133E5;EGYPTIAN HIEROGLYPH Z002;Lo;0;L;;;;;N;;;;;
+133E6;EGYPTIAN HIEROGLYPH Z002A;Lo;0;L;;;;;N;;;;;
+133E7;EGYPTIAN HIEROGLYPH Z002B;Lo;0;L;;;;;N;;;;;
+133E8;EGYPTIAN HIEROGLYPH Z002C;Lo;0;L;;;;;N;;;;;
+133E9;EGYPTIAN HIEROGLYPH Z002D;Lo;0;L;;;;;N;;;;;
+133EA;EGYPTIAN HIEROGLYPH Z003;Lo;0;L;;;;;N;;;;;
+133EB;EGYPTIAN HIEROGLYPH Z003A;Lo;0;L;;;;;N;;;;;
+133EC;EGYPTIAN HIEROGLYPH Z003B;Lo;0;L;;;;;N;;;;;
+133ED;EGYPTIAN HIEROGLYPH Z004;Lo;0;L;;;;;N;;;;;
+133EE;EGYPTIAN HIEROGLYPH Z004A;Lo;0;L;;;;;N;;;;;
+133EF;EGYPTIAN HIEROGLYPH Z005;Lo;0;L;;;;;N;;;;;
+133F0;EGYPTIAN HIEROGLYPH Z005A;Lo;0;L;;;;;N;;;;;
+133F1;EGYPTIAN HIEROGLYPH Z006;Lo;0;L;;;;;N;;;;;
+133F2;EGYPTIAN HIEROGLYPH Z007;Lo;0;L;;;;;N;;;;;
+133F3;EGYPTIAN HIEROGLYPH Z008;Lo;0;L;;;;;N;;;;;
+133F4;EGYPTIAN HIEROGLYPH Z009;Lo;0;L;;;;;N;;;;;
+133F5;EGYPTIAN HIEROGLYPH Z010;Lo;0;L;;;;;N;;;;;
+133F6;EGYPTIAN HIEROGLYPH Z011;Lo;0;L;;;;;N;;;;;
+133F7;EGYPTIAN HIEROGLYPH Z012;Lo;0;L;;;;;N;;;;;
+133F8;EGYPTIAN HIEROGLYPH Z013;Lo;0;L;;;;;N;;;;;
+133F9;EGYPTIAN HIEROGLYPH Z014;Lo;0;L;;;;;N;;;;;
+133FA;EGYPTIAN HIEROGLYPH Z015;Lo;0;L;;;;;N;;;;;
+133FB;EGYPTIAN HIEROGLYPH Z015A;Lo;0;L;;;;;N;;;;;
+133FC;EGYPTIAN HIEROGLYPH Z015B;Lo;0;L;;;;;N;;;;;
+133FD;EGYPTIAN HIEROGLYPH Z015C;Lo;0;L;;;;;N;;;;;
+133FE;EGYPTIAN HIEROGLYPH Z015D;Lo;0;L;;;;;N;;;;;
+133FF;EGYPTIAN HIEROGLYPH Z015E;Lo;0;L;;;;;N;;;;;
+13400;EGYPTIAN HIEROGLYPH Z015F;Lo;0;L;;;;;N;;;;;
+13401;EGYPTIAN HIEROGLYPH Z015G;Lo;0;L;;;;;N;;;;;
+13402;EGYPTIAN HIEROGLYPH Z015H;Lo;0;L;;;;;N;;;;;
+13403;EGYPTIAN HIEROGLYPH Z015I;Lo;0;L;;;;;N;;;;;
+13404;EGYPTIAN HIEROGLYPH Z016;Lo;0;L;;;;;N;;;;;
+13405;EGYPTIAN HIEROGLYPH Z016A;Lo;0;L;;;;;N;;;;;
+13406;EGYPTIAN HIEROGLYPH Z016B;Lo;0;L;;;;;N;;;;;
+13407;EGYPTIAN HIEROGLYPH Z016C;Lo;0;L;;;;;N;;;;;
+13408;EGYPTIAN HIEROGLYPH Z016D;Lo;0;L;;;;;N;;;;;
+13409;EGYPTIAN HIEROGLYPH Z016E;Lo;0;L;;;;;N;;;;;
+1340A;EGYPTIAN HIEROGLYPH Z016F;Lo;0;L;;;;;N;;;;;
+1340B;EGYPTIAN HIEROGLYPH Z016G;Lo;0;L;;;;;N;;;;;
+1340C;EGYPTIAN HIEROGLYPH Z016H;Lo;0;L;;;;;N;;;;;
+1340D;EGYPTIAN HIEROGLYPH AA001;Lo;0;L;;;;;N;;;;;
+1340E;EGYPTIAN HIEROGLYPH AA002;Lo;0;L;;;;;N;;;;;
+1340F;EGYPTIAN HIEROGLYPH AA003;Lo;0;L;;;;;N;;;;;
+13410;EGYPTIAN HIEROGLYPH AA004;Lo;0;L;;;;;N;;;;;
+13411;EGYPTIAN HIEROGLYPH AA005;Lo;0;L;;;;;N;;;;;
+13412;EGYPTIAN HIEROGLYPH AA006;Lo;0;L;;;;;N;;;;;
+13413;EGYPTIAN HIEROGLYPH AA007;Lo;0;L;;;;;N;;;;;
+13414;EGYPTIAN HIEROGLYPH AA007A;Lo;0;L;;;;;N;;;;;
+13415;EGYPTIAN HIEROGLYPH AA007B;Lo;0;L;;;;;N;;;;;
+13416;EGYPTIAN HIEROGLYPH AA008;Lo;0;L;;;;;N;;;;;
+13417;EGYPTIAN HIEROGLYPH AA009;Lo;0;L;;;;;N;;;;;
+13418;EGYPTIAN HIEROGLYPH AA010;Lo;0;L;;;;;N;;;;;
+13419;EGYPTIAN HIEROGLYPH AA011;Lo;0;L;;;;;N;;;;;
+1341A;EGYPTIAN HIEROGLYPH AA012;Lo;0;L;;;;;N;;;;;
+1341B;EGYPTIAN HIEROGLYPH AA013;Lo;0;L;;;;;N;;;;;
+1341C;EGYPTIAN HIEROGLYPH AA014;Lo;0;L;;;;;N;;;;;
+1341D;EGYPTIAN HIEROGLYPH AA015;Lo;0;L;;;;;N;;;;;
+1341E;EGYPTIAN HIEROGLYPH AA016;Lo;0;L;;;;;N;;;;;
+1341F;EGYPTIAN HIEROGLYPH AA017;Lo;0;L;;;;;N;;;;;
+13420;EGYPTIAN HIEROGLYPH AA018;Lo;0;L;;;;;N;;;;;
+13421;EGYPTIAN HIEROGLYPH AA019;Lo;0;L;;;;;N;;;;;
+13422;EGYPTIAN HIEROGLYPH AA020;Lo;0;L;;;;;N;;;;;
+13423;EGYPTIAN HIEROGLYPH AA021;Lo;0;L;;;;;N;;;;;
+13424;EGYPTIAN HIEROGLYPH AA022;Lo;0;L;;;;;N;;;;;
+13425;EGYPTIAN HIEROGLYPH AA023;Lo;0;L;;;;;N;;;;;
+13426;EGYPTIAN HIEROGLYPH AA024;Lo;0;L;;;;;N;;;;;
+13427;EGYPTIAN HIEROGLYPH AA025;Lo;0;L;;;;;N;;;;;
+13428;EGYPTIAN HIEROGLYPH AA026;Lo;0;L;;;;;N;;;;;
+13429;EGYPTIAN HIEROGLYPH AA027;Lo;0;L;;;;;N;;;;;
+1342A;EGYPTIAN HIEROGLYPH AA028;Lo;0;L;;;;;N;;;;;
+1342B;EGYPTIAN HIEROGLYPH AA029;Lo;0;L;;;;;N;;;;;
+1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;;
+1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;;
+1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;;
+1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;;
+1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;;
+1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;;
+1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;;
+1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;;
+1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;;
+1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;;
+1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;;
+1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;;
+1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;;
+1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;;
+1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;;
+1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;;
+1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;;
+1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;;
+1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;;
+1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;;
+1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;;
+1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;;
+1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;;
+1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;;
+1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;;
+1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;;
+1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;;
+1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;;
+1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;;
+1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;;
+1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;;
+1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;;
+1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;;
+1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;;
+1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;;
+1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;;
+1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;;
+1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;;
+1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;;
+1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;;
+1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;;
+1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;;
+1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;;
+1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;;
+1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;;
+1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;;
+1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;;
+1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;;
+1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;;
+1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;;
+1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;;
+1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;;
+1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;;
+1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;;
+1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;;
+1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;;
+1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;;
+1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;;
+1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;;
+1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;;
+1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;;
+1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;;
+1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;;
+1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;;
+1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;;
+1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;;
+1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;;
+1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;;
+1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;;
+1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;;
+1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;;
+1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;;
+1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;;
+1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;;
+1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;;
+1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;;
+1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;;
+1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;;
+1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;;
+1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;;
+1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;;
+1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;;
+1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;;
+1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;;
+1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;;
+1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;;
+1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;;
+1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;;
+1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;;
+1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;;
+1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;;
+1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;;
+1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;;
+1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;;
+1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;;
+1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;;
+1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;;
+1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;;
+1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;;
+1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;;
+1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;;
+1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;;
+1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;;
+1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;;
+1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;;
+1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;;
+1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;;
+1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;;
+1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;;
+1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;;
+1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;;
+1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;;
+1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;;
+1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;;
+1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;;
+1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;;
+1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;;
+1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;;
+1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;;
+1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;;
+1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;;
+1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;;
+1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;;
+1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;;
+1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;;
+1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;;
+1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;;
+1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;;
+1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;;
+1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;;
+1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;;
+1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;;
+1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;;
+1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;;
+1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;;
+1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;;
+1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;;
+1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;;
+1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;;
+1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;;
+1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;;
+1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;;
+1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;;
+1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;;
+1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;;
+1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;;
+1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;;
+1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;;
+1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;;
+1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;;
+1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;;
+1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;;
+1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;;
+1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;;
+1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;;
+1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;;
+1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;;
+1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;;
+1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;;
+1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;;
+1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;;
+1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;;
+1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;;
+1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;;
+1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;;
+1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;;
+1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;;
+1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;;
+1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;;
+1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;;
+1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;;
+1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;;
+1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;;
+1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;;
+1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;;
+1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;;
+1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;;
+1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;;
+1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;;
+1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;;
+1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;;
+1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;;
+1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;;
+1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;;
+1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;;
+1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;;
+1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;;
+1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;;
+1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;;
+1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;;
+1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;;
+1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;;
+1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;;
+1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;;
+1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;;
+1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;;
+1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;;
+1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;;
+1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;;
+1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;;
+1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;;
+1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;;
+1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;;
+1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;;
+1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;;
+1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;;
+1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;;
+1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;;
+1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;;
+1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;;
+1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;;
+1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;;
+1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;;
+1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;;
+1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;;
+1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;;
+1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;;
+1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;;
+1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;;
+1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;;
+1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;;
+1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;;
+1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;;
+1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;;
+1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;;
+1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;;
+1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;;
+1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;;
+1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;;
+1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;;
+1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;;
+1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;;
+1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;;
+1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;;
+1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;;
+1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;;
+1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;;
+1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;;
+1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;;
+1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;;
+1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;;
+1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;;
+1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;;
+1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;;
+1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;;
+1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;;
+1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;;
+1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;;
+1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;;
+1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;;
+1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;;
+1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;;
+1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;;
+1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;;
+1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;;
+1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;;
+1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;;
+1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;;
+1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;;
+1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;;
+1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;;
+1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;;
+1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;;
+1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;;
+1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;;
+1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;;
+1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;;
+1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;;
+1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;;
+1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;;
+1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;;
+1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;;
+1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;;
+1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;;
+1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;;
+1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;;
+1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;;
+1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;;
+1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;;
+1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;;
+1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;;
+1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;;
+1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;;
+1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;;
+1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;;
+1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;;
+1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;;
+1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;;
+1D129;MUSICAL SYMBOL MULTIPLE MEASURE REST;So;0;L;;;;;N;;;;;
+1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;;
+1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;;
+1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;;
+1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;;
+1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;;
+1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;;
+1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;;
+1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;;
+1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;;
+1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;;
+1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;;
+1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;;
+1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;;
+1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;;
+1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;;
+1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;;
+1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;;
+1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;;
+1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;;
+1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;;
+1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;;
+1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;;
+1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;;
+1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;;
+1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;;
+1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;;
+1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;;
+1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;;
+1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;;
+1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
+1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;;
+1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;;
+1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;;
+1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;;
+1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;;
+1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;;
+1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;;
+1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;;
+1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;;
+1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;;
+1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;;
+1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
+1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;;
+1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;;
+1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;;
+1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;;
+1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
+1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;;
+1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;;
+1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;;
+1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;;
+1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;;
+1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;;
+1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;;
+1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;;
+1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;;
+1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;;
+1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;;
+1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;;
+1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;;
+1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;;
+1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;;
+1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;;
+1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;;
+1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;;
+1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;;
+1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;;
+1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;;
+1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;;
+1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;;
+1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;;
+1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;;
+1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;;
+1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;;
+1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;;
+1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;;
+1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;;
+1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;;
+1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;;
+1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;;
+1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;;
+1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;;
+1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;;
+1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;;
+1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;;
+1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;;
+1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;;
+1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;;
+1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;;
+1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;;
+1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;;
+1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;;
+1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;;
+1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;;
+1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;;
+1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;;
+1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;;
+1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;;
+1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;;
+1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;;
+1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;;
+1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;;
+1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;;
+1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;;
+1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;;
+1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;;
+1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;;
+1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;;
+1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;;
+1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;;
+1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;;
+1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;;
+1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;;
+1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;;
+1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;;
+1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;;
+1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;;
+1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;;
+1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;;
+1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;;
+1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;;
+1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;;
+1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;;
+1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;;
+1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;;
+1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;;
+1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;;
+1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;;
+1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;;
+1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;;
+1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;;
+1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;;
+1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;;
+1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;;
+1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;;
+1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;;
+1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;;
+1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;;
+1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;;
+1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;;
+1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;;
+1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;;
+1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;;
+1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;;
+1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;;
+1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;;
+1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;;
+1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;;
+1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;;
+1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;;
+1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;;
+1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;;
+1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;;
+1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;;
+1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;;
+1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;;
+1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;;
+1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;;
+1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;;
+1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;;
+1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;;
+1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;;
+1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;;
+1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;;
+1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;;
+1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;;
+1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;;
+1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;;
+1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;;
+1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;;
+1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;;
+1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;;
+1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;;
+1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;;
+1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;;
+1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;;
+1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;;
+1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;;
+1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;;
+1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;;
+1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;;
+1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;;
+1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;;
+1D203;GREEK VOCAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;;
+1D204;GREEK VOCAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;;
+1D205;GREEK VOCAL NOTATION SYMBOL-6;So;0;ON;;;;;N;;;;;
+1D206;GREEK VOCAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;;
+1D207;GREEK VOCAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;;
+1D208;GREEK VOCAL NOTATION SYMBOL-9;So;0;ON;;;;;N;;;;;
+1D209;GREEK VOCAL NOTATION SYMBOL-10;So;0;ON;;;;;N;;;;;
+1D20A;GREEK VOCAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;;
+1D20B;GREEK VOCAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;;
+1D20C;GREEK VOCAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;;
+1D20D;GREEK VOCAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;;
+1D20E;GREEK VOCAL NOTATION SYMBOL-15;So;0;ON;;;;;N;;;;;
+1D20F;GREEK VOCAL NOTATION SYMBOL-16;So;0;ON;;;;;N;;;;;
+1D210;GREEK VOCAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;;
+1D211;GREEK VOCAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;;
+1D212;GREEK VOCAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;;
+1D213;GREEK VOCAL NOTATION SYMBOL-20;So;0;ON;;;;;N;;;;;
+1D214;GREEK VOCAL NOTATION SYMBOL-21;So;0;ON;;;;;N;;;;;
+1D215;GREEK VOCAL NOTATION SYMBOL-22;So;0;ON;;;;;N;;;;;
+1D216;GREEK VOCAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;;
+1D217;GREEK VOCAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;;
+1D218;GREEK VOCAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;;
+1D219;GREEK VOCAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;;
+1D21A;GREEK VOCAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;;
+1D21B;GREEK VOCAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;;
+1D21C;GREEK VOCAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;;
+1D21D;GREEK INSTRUMENTAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;;
+1D21E;GREEK INSTRUMENTAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;;
+1D21F;GREEK INSTRUMENTAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;;
+1D220;GREEK INSTRUMENTAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;;
+1D221;GREEK INSTRUMENTAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;;
+1D222;GREEK INSTRUMENTAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;;
+1D223;GREEK INSTRUMENTAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;;
+1D224;GREEK INSTRUMENTAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;;
+1D225;GREEK INSTRUMENTAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;;
+1D226;GREEK INSTRUMENTAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;;
+1D227;GREEK INSTRUMENTAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;;
+1D228;GREEK INSTRUMENTAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;;
+1D229;GREEK INSTRUMENTAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;;
+1D22A;GREEK INSTRUMENTAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;;
+1D22B;GREEK INSTRUMENTAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;;
+1D22C;GREEK INSTRUMENTAL NOTATION SYMBOL-25;So;0;ON;;;;;N;;;;;
+1D22D;GREEK INSTRUMENTAL NOTATION SYMBOL-26;So;0;ON;;;;;N;;;;;
+1D22E;GREEK INSTRUMENTAL NOTATION SYMBOL-27;So;0;ON;;;;;N;;;;;
+1D22F;GREEK INSTRUMENTAL NOTATION SYMBOL-29;So;0;ON;;;;;N;;;;;
+1D230;GREEK INSTRUMENTAL NOTATION SYMBOL-30;So;0;ON;;;;;N;;;;;
+1D231;GREEK INSTRUMENTAL NOTATION SYMBOL-32;So;0;ON;;;;;N;;;;;
+1D232;GREEK INSTRUMENTAL NOTATION SYMBOL-36;So;0;ON;;;;;N;;;;;
+1D233;GREEK INSTRUMENTAL NOTATION SYMBOL-37;So;0;ON;;;;;N;;;;;
+1D234;GREEK INSTRUMENTAL NOTATION SYMBOL-38;So;0;ON;;;;;N;;;;;
+1D235;GREEK INSTRUMENTAL NOTATION SYMBOL-39;So;0;ON;;;;;N;;;;;
+1D236;GREEK INSTRUMENTAL NOTATION SYMBOL-40;So;0;ON;;;;;N;;;;;
+1D237;GREEK INSTRUMENTAL NOTATION SYMBOL-42;So;0;ON;;;;;N;;;;;
+1D238;GREEK INSTRUMENTAL NOTATION SYMBOL-43;So;0;ON;;;;;N;;;;;
+1D239;GREEK INSTRUMENTAL NOTATION SYMBOL-45;So;0;ON;;;;;N;;;;;
+1D23A;GREEK INSTRUMENTAL NOTATION SYMBOL-47;So;0;ON;;;;;N;;;;;
+1D23B;GREEK INSTRUMENTAL NOTATION SYMBOL-48;So;0;ON;;;;;N;;;;;
+1D23C;GREEK INSTRUMENTAL NOTATION SYMBOL-49;So;0;ON;;;;;N;;;;;
+1D23D;GREEK INSTRUMENTAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;;
+1D23E;GREEK INSTRUMENTAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;;
+1D23F;GREEK INSTRUMENTAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;;
+1D240;GREEK INSTRUMENTAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;;
+1D241;GREEK INSTRUMENTAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;;
+1D242;COMBINING GREEK MUSICAL TRISEME;Mn;230;NSM;;;;;N;;;;;
+1D243;COMBINING GREEK MUSICAL TETRASEME;Mn;230;NSM;;;;;N;;;;;
+1D244;COMBINING GREEK MUSICAL PENTASEME;Mn;230;NSM;;;;;N;;;;;
+1D245;GREEK MUSICAL LEIMMA;So;0;ON;;;;;N;;;;;
+1D300;MONOGRAM FOR EARTH;So;0;ON;;;;;N;;;;;
+1D301;DIGRAM FOR HEAVENLY EARTH;So;0;ON;;;;;N;;;;;
+1D302;DIGRAM FOR HUMAN EARTH;So;0;ON;;;;;N;;;;;
+1D303;DIGRAM FOR EARTHLY HEAVEN;So;0;ON;;;;;N;;;;;
+1D304;DIGRAM FOR EARTHLY HUMAN;So;0;ON;;;;;N;;;;;
+1D305;DIGRAM FOR EARTH;So;0;ON;;;;;N;;;;;
+1D306;TETRAGRAM FOR CENTRE;So;0;ON;;;;;N;;;;;
+1D307;TETRAGRAM FOR FULL CIRCLE;So;0;ON;;;;;N;;;;;
+1D308;TETRAGRAM FOR MIRED;So;0;ON;;;;;N;;;;;
+1D309;TETRAGRAM FOR BARRIER;So;0;ON;;;;;N;;;;;
+1D30A;TETRAGRAM FOR KEEPING SMALL;So;0;ON;;;;;N;;;;;
+1D30B;TETRAGRAM FOR CONTRARIETY;So;0;ON;;;;;N;;;;;
+1D30C;TETRAGRAM FOR ASCENT;So;0;ON;;;;;N;;;;;
+1D30D;TETRAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;;
+1D30E;TETRAGRAM FOR BRANCHING OUT;So;0;ON;;;;;N;;;;;
+1D30F;TETRAGRAM FOR DEFECTIVENESS OR DISTORTION;So;0;ON;;;;;N;;;;;
+1D310;TETRAGRAM FOR DIVERGENCE;So;0;ON;;;;;N;;;;;
+1D311;TETRAGRAM FOR YOUTHFULNESS;So;0;ON;;;;;N;;;;;
+1D312;TETRAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;;
+1D313;TETRAGRAM FOR PENETRATION;So;0;ON;;;;;N;;;;;
+1D314;TETRAGRAM FOR REACH;So;0;ON;;;;;N;;;;;
+1D315;TETRAGRAM FOR CONTACT;So;0;ON;;;;;N;;;;;
+1D316;TETRAGRAM FOR HOLDING BACK;So;0;ON;;;;;N;;;;;
+1D317;TETRAGRAM FOR WAITING;So;0;ON;;;;;N;;;;;
+1D318;TETRAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;;
+1D319;TETRAGRAM FOR ADVANCE;So;0;ON;;;;;N;;;;;
+1D31A;TETRAGRAM FOR RELEASE;So;0;ON;;;;;N;;;;;
+1D31B;TETRAGRAM FOR RESISTANCE;So;0;ON;;;;;N;;;;;
+1D31C;TETRAGRAM FOR EASE;So;0;ON;;;;;N;;;;;
+1D31D;TETRAGRAM FOR JOY;So;0;ON;;;;;N;;;;;
+1D31E;TETRAGRAM FOR CONTENTION;So;0;ON;;;;;N;;;;;
+1D31F;TETRAGRAM FOR ENDEAVOUR;So;0;ON;;;;;N;;;;;
+1D320;TETRAGRAM FOR DUTIES;So;0;ON;;;;;N;;;;;
+1D321;TETRAGRAM FOR CHANGE;So;0;ON;;;;;N;;;;;
+1D322;TETRAGRAM FOR DECISIVENESS;So;0;ON;;;;;N;;;;;
+1D323;TETRAGRAM FOR BOLD RESOLUTION;So;0;ON;;;;;N;;;;;
+1D324;TETRAGRAM FOR PACKING;So;0;ON;;;;;N;;;;;
+1D325;TETRAGRAM FOR LEGION;So;0;ON;;;;;N;;;;;
+1D326;TETRAGRAM FOR CLOSENESS;So;0;ON;;;;;N;;;;;
+1D327;TETRAGRAM FOR KINSHIP;So;0;ON;;;;;N;;;;;
+1D328;TETRAGRAM FOR GATHERING;So;0;ON;;;;;N;;;;;
+1D329;TETRAGRAM FOR STRENGTH;So;0;ON;;;;;N;;;;;
+1D32A;TETRAGRAM FOR PURITY;So;0;ON;;;;;N;;;;;
+1D32B;TETRAGRAM FOR FULLNESS;So;0;ON;;;;;N;;;;;
+1D32C;TETRAGRAM FOR RESIDENCE;So;0;ON;;;;;N;;;;;
+1D32D;TETRAGRAM FOR LAW OR MODEL;So;0;ON;;;;;N;;;;;
+1D32E;TETRAGRAM FOR RESPONSE;So;0;ON;;;;;N;;;;;
+1D32F;TETRAGRAM FOR GOING TO MEET;So;0;ON;;;;;N;;;;;
+1D330;TETRAGRAM FOR ENCOUNTERS;So;0;ON;;;;;N;;;;;
+1D331;TETRAGRAM FOR STOVE;So;0;ON;;;;;N;;;;;
+1D332;TETRAGRAM FOR GREATNESS;So;0;ON;;;;;N;;;;;
+1D333;TETRAGRAM FOR ENLARGEMENT;So;0;ON;;;;;N;;;;;
+1D334;TETRAGRAM FOR PATTERN;So;0;ON;;;;;N;;;;;
+1D335;TETRAGRAM FOR RITUAL;So;0;ON;;;;;N;;;;;
+1D336;TETRAGRAM FOR FLIGHT;So;0;ON;;;;;N;;;;;
+1D337;TETRAGRAM FOR VASTNESS OR WASTING;So;0;ON;;;;;N;;;;;
+1D338;TETRAGRAM FOR CONSTANCY;So;0;ON;;;;;N;;;;;
+1D339;TETRAGRAM FOR MEASURE;So;0;ON;;;;;N;;;;;
+1D33A;TETRAGRAM FOR ETERNITY;So;0;ON;;;;;N;;;;;
+1D33B;TETRAGRAM FOR UNITY;So;0;ON;;;;;N;;;;;
+1D33C;TETRAGRAM FOR DIMINISHMENT;So;0;ON;;;;;N;;;;;
+1D33D;TETRAGRAM FOR CLOSED MOUTH;So;0;ON;;;;;N;;;;;
+1D33E;TETRAGRAM FOR GUARDEDNESS;So;0;ON;;;;;N;;;;;
+1D33F;TETRAGRAM FOR GATHERING IN;So;0;ON;;;;;N;;;;;
+1D340;TETRAGRAM FOR MASSING;So;0;ON;;;;;N;;;;;
+1D341;TETRAGRAM FOR ACCUMULATION;So;0;ON;;;;;N;;;;;
+1D342;TETRAGRAM FOR EMBELLISHMENT;So;0;ON;;;;;N;;;;;
+1D343;TETRAGRAM FOR DOUBT;So;0;ON;;;;;N;;;;;
+1D344;TETRAGRAM FOR WATCH;So;0;ON;;;;;N;;;;;
+1D345;TETRAGRAM FOR SINKING;So;0;ON;;;;;N;;;;;
+1D346;TETRAGRAM FOR INNER;So;0;ON;;;;;N;;;;;
+1D347;TETRAGRAM FOR DEPARTURE;So;0;ON;;;;;N;;;;;
+1D348;TETRAGRAM FOR DARKENING;So;0;ON;;;;;N;;;;;
+1D349;TETRAGRAM FOR DIMMING;So;0;ON;;;;;N;;;;;
+1D34A;TETRAGRAM FOR EXHAUSTION;So;0;ON;;;;;N;;;;;
+1D34B;TETRAGRAM FOR SEVERANCE;So;0;ON;;;;;N;;;;;
+1D34C;TETRAGRAM FOR STOPPAGE;So;0;ON;;;;;N;;;;;
+1D34D;TETRAGRAM FOR HARDNESS;So;0;ON;;;;;N;;;;;
+1D34E;TETRAGRAM FOR COMPLETION;So;0;ON;;;;;N;;;;;
+1D34F;TETRAGRAM FOR CLOSURE;So;0;ON;;;;;N;;;;;
+1D350;TETRAGRAM FOR FAILURE;So;0;ON;;;;;N;;;;;
+1D351;TETRAGRAM FOR AGGRAVATION;So;0;ON;;;;;N;;;;;
+1D352;TETRAGRAM FOR COMPLIANCE;So;0;ON;;;;;N;;;;;
+1D353;TETRAGRAM FOR ON THE VERGE;So;0;ON;;;;;N;;;;;
+1D354;TETRAGRAM FOR DIFFICULTIES;So;0;ON;;;;;N;;;;;
+1D355;TETRAGRAM FOR LABOURING;So;0;ON;;;;;N;;;;;
+1D356;TETRAGRAM FOR FOSTERING;So;0;ON;;;;;N;;;;;
+1D360;COUNTING ROD UNIT DIGIT ONE;No;0;L;;;;1;N;;;;;
+1D361;COUNTING ROD UNIT DIGIT TWO;No;0;L;;;;2;N;;;;;
+1D362;COUNTING ROD UNIT DIGIT THREE;No;0;L;;;;3;N;;;;;
+1D363;COUNTING ROD UNIT DIGIT FOUR;No;0;L;;;;4;N;;;;;
+1D364;COUNTING ROD UNIT DIGIT FIVE;No;0;L;;;;5;N;;;;;
+1D365;COUNTING ROD UNIT DIGIT SIX;No;0;L;;;;6;N;;;;;
+1D366;COUNTING ROD UNIT DIGIT SEVEN;No;0;L;;;;7;N;;;;;
+1D367;COUNTING ROD UNIT DIGIT EIGHT;No;0;L;;;;8;N;;;;;
+1D368;COUNTING ROD UNIT DIGIT NINE;No;0;L;;;;9;N;;;;;
+1D369;COUNTING ROD TENS DIGIT ONE;No;0;L;;;;10;N;;;;;
+1D36A;COUNTING ROD TENS DIGIT TWO;No;0;L;;;;20;N;;;;;
+1D36B;COUNTING ROD TENS DIGIT THREE;No;0;L;;;;30;N;;;;;
+1D36C;COUNTING ROD TENS DIGIT FOUR;No;0;L;;;;40;N;;;;;
+1D36D;COUNTING ROD TENS DIGIT FIVE;No;0;L;;;;50;N;;;;;
+1D36E;COUNTING ROD TENS DIGIT SIX;No;0;L;;;;60;N;;;;;
+1D36F;COUNTING ROD TENS DIGIT SEVEN;No;0;L;;;;70;N;;;;;
+1D370;COUNTING ROD TENS DIGIT EIGHT;No;0;L;;;;80;N;;;;;
+1D371;COUNTING ROD TENS DIGIT NINE;No;0;L;;;;90;N;;;;;
+1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D4C1;MATHEMATICAL SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;;
+1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;;
+1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;;
+1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;;
+1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;;
+1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;;
+1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;;
+1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;;
+1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;;
+1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;;
+1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;;
+1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;;
+1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;;
+1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;;
+1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;;
+1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;;
+1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;;
+1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;;
+1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;;
+1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;;
+1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;;
+1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;;
+1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;;
+1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;;
+1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;;
+1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;;
+1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L;<font> 0061;;;;N;;;;;
+1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L;<font> 0062;;;;N;;;;;
+1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L;<font> 0063;;;;N;;;;;
+1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L;<font> 0064;;;;N;;;;;
+1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L;<font> 0065;;;;N;;;;;
+1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L;<font> 0066;;;;N;;;;;
+1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L;<font> 0067;;;;N;;;;;
+1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L;<font> 0068;;;;N;;;;;
+1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L;<font> 0069;;;;N;;;;;
+1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L;<font> 006A;;;;N;;;;;
+1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L;<font> 006B;;;;N;;;;;
+1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L;<font> 006C;;;;N;;;;;
+1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L;<font> 006D;;;;N;;;;;
+1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L;<font> 006E;;;;N;;;;;
+1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L;<font> 006F;;;;N;;;;;
+1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L;<font> 0070;;;;N;;;;;
+1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;;
+1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L;<font> 0072;;;;N;;;;;
+1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L;<font> 0073;;;;N;;;;;
+1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L;<font> 0074;;;;N;;;;;
+1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L;<font> 0075;;;;N;;;;;
+1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L;<font> 0076;;;;N;;;;;
+1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L;<font> 0077;;;;N;;;;;
+1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L;<font> 0078;;;;N;;;;;
+1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;;
+1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;;
+1D6A4;MATHEMATICAL ITALIC SMALL DOTLESS I;Ll;0;L;<font> 0131;;;;N;;;;;
+1D6A5;MATHEMATICAL ITALIC SMALL DOTLESS J;Ll;0;L;<font> 0237;;;;N;;;;;
+1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
+1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
+1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
+1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
+1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
+1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
+1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
+1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
+1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
+1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
+1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
+1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
+1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
+1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
+1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
+1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
+1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
+1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
+1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
+1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
+1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
+1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
+1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
+1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
+1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
+1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
+1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
+1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
+1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
+1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
+1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
+1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
+1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
+1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
+1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
+1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
+1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
+1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
+1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
+1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
+1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
+1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
+1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
+1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
+1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
+1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
+1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
+1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
+1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
+1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
+1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
+1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
+1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
+1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
+1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
+1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
+1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
+1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
+1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
+1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
+1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
+1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
+1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
+1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
+1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
+1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
+1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
+1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
+1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
+1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
+1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
+1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
+1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
+1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
+1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
+1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
+1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
+1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
+1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
+1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
+1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
+1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
+1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
+1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
+1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
+1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
+1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
+1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
+1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
+1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
+1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
+1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
+1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
+1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
+1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
+1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
+1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
+1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
+1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
+1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
+1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
+1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
+1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
+1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
+1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
+1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
+1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
+1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
+1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
+1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
+1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
+1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
+1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
+1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
+1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
+1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
+1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
+1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
+1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
+1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
+1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
+1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
+1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
+1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
+1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
+1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
+1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
+1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
+1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
+1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
+1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
+1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
+1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
+1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
+1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
+1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
+1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
+1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
+1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
+1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
+1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
+1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
+1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
+1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
+1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
+1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
+1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
+1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
+1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
+1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
+1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
+1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
+1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
+1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
+1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
+1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
+1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
+1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
+1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
+1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
+1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
+1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
+1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
+1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
+1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
+1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
+1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
+1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
+1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
+1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
+1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
+1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
+1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
+1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
+1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
+1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
+1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
+1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
+1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
+1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
+1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
+1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
+1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
+1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
+1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
+1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
+1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
+1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
+1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
+1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
+1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
+1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
+1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
+1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
+1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
+1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
+1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
+1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
+1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
+1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
+1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
+1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
+1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
+1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
+1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
+1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
+1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
+1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
+1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
+1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
+1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
+1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
+1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
+1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
+1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
+1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
+1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
+1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
+1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
+1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
+1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
+1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
+1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
+1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
+1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
+1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
+1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
+1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
+1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
+1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
+1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
+1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
+1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;;
+1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;;
+1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;;
+1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;;
+1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;;
+1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;;
+1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;;
+1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;;
+1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;;
+1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;;
+1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;;
+1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;;
+1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;;
+1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;;
+1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;;
+1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;;
+1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;;
+1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;;
+1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;;
+1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;;
+1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;;
+1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;;
+1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;;
+1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;;
+1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;;
+1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;;
+1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;;
+1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;;
+1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;;
+1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;;
+1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;;
+1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;;
+1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;;
+1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;;
+1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;;
+1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;;
+1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;;
+1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;;
+1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;;
+1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;;
+1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;;
+1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;;
+1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;;
+1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;;
+1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;;
+1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;;
+1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;;
+1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;;
+1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;;
+1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;;
+1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;;
+1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;;
+1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;;
+1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;;
+1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;;
+1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;;
+1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;;
+1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;;
+1D7CA;MATHEMATICAL BOLD CAPITAL DIGAMMA;Lu;0;L;<font> 03DC;;;;N;;;;;
+1D7CB;MATHEMATICAL BOLD SMALL DIGAMMA;Ll;0;L;<font> 03DD;;;;N;;;;;
+1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
+1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
+1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
+1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
+1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
+1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
+1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
+1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
+1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
+1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
+1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
+1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
+1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
+1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
+1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
+1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
+1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
+1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
+1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
+1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
+1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
+1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
+1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
+1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
+1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
+1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
+1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
+1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
+1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
+1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
+1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
+1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
+1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
+1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
+1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
+1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
+1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
+1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
+1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
+1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
+1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;;
+1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;;
+1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;;
+1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;;
+1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;;
+1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;;
+1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;;
+1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
+1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
+1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
+1F000;MAHJONG TILE EAST WIND;So;0;ON;;;;;N;;;;;
+1F001;MAHJONG TILE SOUTH WIND;So;0;ON;;;;;N;;;;;
+1F002;MAHJONG TILE WEST WIND;So;0;ON;;;;;N;;;;;
+1F003;MAHJONG TILE NORTH WIND;So;0;ON;;;;;N;;;;;
+1F004;MAHJONG TILE RED DRAGON;So;0;ON;;;;;N;;;;;
+1F005;MAHJONG TILE GREEN DRAGON;So;0;ON;;;;;N;;;;;
+1F006;MAHJONG TILE WHITE DRAGON;So;0;ON;;;;;N;;;;;
+1F007;MAHJONG TILE ONE OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F008;MAHJONG TILE TWO OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F009;MAHJONG TILE THREE OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F00A;MAHJONG TILE FOUR OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F00B;MAHJONG TILE FIVE OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F00C;MAHJONG TILE SIX OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F00D;MAHJONG TILE SEVEN OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F00E;MAHJONG TILE EIGHT OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F00F;MAHJONG TILE NINE OF CHARACTERS;So;0;ON;;;;;N;;;;;
+1F010;MAHJONG TILE ONE OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F011;MAHJONG TILE TWO OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F012;MAHJONG TILE THREE OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F013;MAHJONG TILE FOUR OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F014;MAHJONG TILE FIVE OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F015;MAHJONG TILE SIX OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F016;MAHJONG TILE SEVEN OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F017;MAHJONG TILE EIGHT OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F018;MAHJONG TILE NINE OF BAMBOOS;So;0;ON;;;;;N;;;;;
+1F019;MAHJONG TILE ONE OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F01A;MAHJONG TILE TWO OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F01B;MAHJONG TILE THREE OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F01C;MAHJONG TILE FOUR OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F01D;MAHJONG TILE FIVE OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F01E;MAHJONG TILE SIX OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F01F;MAHJONG TILE SEVEN OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F020;MAHJONG TILE EIGHT OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F021;MAHJONG TILE NINE OF CIRCLES;So;0;ON;;;;;N;;;;;
+1F022;MAHJONG TILE PLUM;So;0;ON;;;;;N;;;;;
+1F023;MAHJONG TILE ORCHID;So;0;ON;;;;;N;;;;;
+1F024;MAHJONG TILE BAMBOO;So;0;ON;;;;;N;;;;;
+1F025;MAHJONG TILE CHRYSANTHEMUM;So;0;ON;;;;;N;;;;;
+1F026;MAHJONG TILE SPRING;So;0;ON;;;;;N;;;;;
+1F027;MAHJONG TILE SUMMER;So;0;ON;;;;;N;;;;;
+1F028;MAHJONG TILE AUTUMN;So;0;ON;;;;;N;;;;;
+1F029;MAHJONG TILE WINTER;So;0;ON;;;;;N;;;;;
+1F02A;MAHJONG TILE JOKER;So;0;ON;;;;;N;;;;;
+1F02B;MAHJONG TILE BACK;So;0;ON;;;;;N;;;;;
+1F030;DOMINO TILE HORIZONTAL BACK;So;0;ON;;;;;N;;;;;
+1F031;DOMINO TILE HORIZONTAL-00-00;So;0;ON;;;;;N;;;;;
+1F032;DOMINO TILE HORIZONTAL-00-01;So;0;ON;;;;;N;;;;;
+1F033;DOMINO TILE HORIZONTAL-00-02;So;0;ON;;;;;N;;;;;
+1F034;DOMINO TILE HORIZONTAL-00-03;So;0;ON;;;;;N;;;;;
+1F035;DOMINO TILE HORIZONTAL-00-04;So;0;ON;;;;;N;;;;;
+1F036;DOMINO TILE HORIZONTAL-00-05;So;0;ON;;;;;N;;;;;
+1F037;DOMINO TILE HORIZONTAL-00-06;So;0;ON;;;;;N;;;;;
+1F038;DOMINO TILE HORIZONTAL-01-00;So;0;ON;;;;;N;;;;;
+1F039;DOMINO TILE HORIZONTAL-01-01;So;0;ON;;;;;N;;;;;
+1F03A;DOMINO TILE HORIZONTAL-01-02;So;0;ON;;;;;N;;;;;
+1F03B;DOMINO TILE HORIZONTAL-01-03;So;0;ON;;;;;N;;;;;
+1F03C;DOMINO TILE HORIZONTAL-01-04;So;0;ON;;;;;N;;;;;
+1F03D;DOMINO TILE HORIZONTAL-01-05;So;0;ON;;;;;N;;;;;
+1F03E;DOMINO TILE HORIZONTAL-01-06;So;0;ON;;;;;N;;;;;
+1F03F;DOMINO TILE HORIZONTAL-02-00;So;0;ON;;;;;N;;;;;
+1F040;DOMINO TILE HORIZONTAL-02-01;So;0;ON;;;;;N;;;;;
+1F041;DOMINO TILE HORIZONTAL-02-02;So;0;ON;;;;;N;;;;;
+1F042;DOMINO TILE HORIZONTAL-02-03;So;0;ON;;;;;N;;;;;
+1F043;DOMINO TILE HORIZONTAL-02-04;So;0;ON;;;;;N;;;;;
+1F044;DOMINO TILE HORIZONTAL-02-05;So;0;ON;;;;;N;;;;;
+1F045;DOMINO TILE HORIZONTAL-02-06;So;0;ON;;;;;N;;;;;
+1F046;DOMINO TILE HORIZONTAL-03-00;So;0;ON;;;;;N;;;;;
+1F047;DOMINO TILE HORIZONTAL-03-01;So;0;ON;;;;;N;;;;;
+1F048;DOMINO TILE HORIZONTAL-03-02;So;0;ON;;;;;N;;;;;
+1F049;DOMINO TILE HORIZONTAL-03-03;So;0;ON;;;;;N;;;;;
+1F04A;DOMINO TILE HORIZONTAL-03-04;So;0;ON;;;;;N;;;;;
+1F04B;DOMINO TILE HORIZONTAL-03-05;So;0;ON;;;;;N;;;;;
+1F04C;DOMINO TILE HORIZONTAL-03-06;So;0;ON;;;;;N;;;;;
+1F04D;DOMINO TILE HORIZONTAL-04-00;So;0;ON;;;;;N;;;;;
+1F04E;DOMINO TILE HORIZONTAL-04-01;So;0;ON;;;;;N;;;;;
+1F04F;DOMINO TILE HORIZONTAL-04-02;So;0;ON;;;;;N;;;;;
+1F050;DOMINO TILE HORIZONTAL-04-03;So;0;ON;;;;;N;;;;;
+1F051;DOMINO TILE HORIZONTAL-04-04;So;0;ON;;;;;N;;;;;
+1F052;DOMINO TILE HORIZONTAL-04-05;So;0;ON;;;;;N;;;;;
+1F053;DOMINO TILE HORIZONTAL-04-06;So;0;ON;;;;;N;;;;;
+1F054;DOMINO TILE HORIZONTAL-05-00;So;0;ON;;;;;N;;;;;
+1F055;DOMINO TILE HORIZONTAL-05-01;So;0;ON;;;;;N;;;;;
+1F056;DOMINO TILE HORIZONTAL-05-02;So;0;ON;;;;;N;;;;;
+1F057;DOMINO TILE HORIZONTAL-05-03;So;0;ON;;;;;N;;;;;
+1F058;DOMINO TILE HORIZONTAL-05-04;So;0;ON;;;;;N;;;;;
+1F059;DOMINO TILE HORIZONTAL-05-05;So;0;ON;;;;;N;;;;;
+1F05A;DOMINO TILE HORIZONTAL-05-06;So;0;ON;;;;;N;;;;;
+1F05B;DOMINO TILE HORIZONTAL-06-00;So;0;ON;;;;;N;;;;;
+1F05C;DOMINO TILE HORIZONTAL-06-01;So;0;ON;;;;;N;;;;;
+1F05D;DOMINO TILE HORIZONTAL-06-02;So;0;ON;;;;;N;;;;;
+1F05E;DOMINO TILE HORIZONTAL-06-03;So;0;ON;;;;;N;;;;;
+1F05F;DOMINO TILE HORIZONTAL-06-04;So;0;ON;;;;;N;;;;;
+1F060;DOMINO TILE HORIZONTAL-06-05;So;0;ON;;;;;N;;;;;
+1F061;DOMINO TILE HORIZONTAL-06-06;So;0;ON;;;;;N;;;;;
+1F062;DOMINO TILE VERTICAL BACK;So;0;ON;;;;;N;;;;;
+1F063;DOMINO TILE VERTICAL-00-00;So;0;ON;;;;;N;;;;;
+1F064;DOMINO TILE VERTICAL-00-01;So;0;ON;;;;;N;;;;;
+1F065;DOMINO TILE VERTICAL-00-02;So;0;ON;;;;;N;;;;;
+1F066;DOMINO TILE VERTICAL-00-03;So;0;ON;;;;;N;;;;;
+1F067;DOMINO TILE VERTICAL-00-04;So;0;ON;;;;;N;;;;;
+1F068;DOMINO TILE VERTICAL-00-05;So;0;ON;;;;;N;;;;;
+1F069;DOMINO TILE VERTICAL-00-06;So;0;ON;;;;;N;;;;;
+1F06A;DOMINO TILE VERTICAL-01-00;So;0;ON;;;;;N;;;;;
+1F06B;DOMINO TILE VERTICAL-01-01;So;0;ON;;;;;N;;;;;
+1F06C;DOMINO TILE VERTICAL-01-02;So;0;ON;;;;;N;;;;;
+1F06D;DOMINO TILE VERTICAL-01-03;So;0;ON;;;;;N;;;;;
+1F06E;DOMINO TILE VERTICAL-01-04;So;0;ON;;;;;N;;;;;
+1F06F;DOMINO TILE VERTICAL-01-05;So;0;ON;;;;;N;;;;;
+1F070;DOMINO TILE VERTICAL-01-06;So;0;ON;;;;;N;;;;;
+1F071;DOMINO TILE VERTICAL-02-00;So;0;ON;;;;;N;;;;;
+1F072;DOMINO TILE VERTICAL-02-01;So;0;ON;;;;;N;;;;;
+1F073;DOMINO TILE VERTICAL-02-02;So;0;ON;;;;;N;;;;;
+1F074;DOMINO TILE VERTICAL-02-03;So;0;ON;;;;;N;;;;;
+1F075;DOMINO TILE VERTICAL-02-04;So;0;ON;;;;;N;;;;;
+1F076;DOMINO TILE VERTICAL-02-05;So;0;ON;;;;;N;;;;;
+1F077;DOMINO TILE VERTICAL-02-06;So;0;ON;;;;;N;;;;;
+1F078;DOMINO TILE VERTICAL-03-00;So;0;ON;;;;;N;;;;;
+1F079;DOMINO TILE VERTICAL-03-01;So;0;ON;;;;;N;;;;;
+1F07A;DOMINO TILE VERTICAL-03-02;So;0;ON;;;;;N;;;;;
+1F07B;DOMINO TILE VERTICAL-03-03;So;0;ON;;;;;N;;;;;
+1F07C;DOMINO TILE VERTICAL-03-04;So;0;ON;;;;;N;;;;;
+1F07D;DOMINO TILE VERTICAL-03-05;So;0;ON;;;;;N;;;;;
+1F07E;DOMINO TILE VERTICAL-03-06;So;0;ON;;;;;N;;;;;
+1F07F;DOMINO TILE VERTICAL-04-00;So;0;ON;;;;;N;;;;;
+1F080;DOMINO TILE VERTICAL-04-01;So;0;ON;;;;;N;;;;;
+1F081;DOMINO TILE VERTICAL-04-02;So;0;ON;;;;;N;;;;;
+1F082;DOMINO TILE VERTICAL-04-03;So;0;ON;;;;;N;;;;;
+1F083;DOMINO TILE VERTICAL-04-04;So;0;ON;;;;;N;;;;;
+1F084;DOMINO TILE VERTICAL-04-05;So;0;ON;;;;;N;;;;;
+1F085;DOMINO TILE VERTICAL-04-06;So;0;ON;;;;;N;;;;;
+1F086;DOMINO TILE VERTICAL-05-00;So;0;ON;;;;;N;;;;;
+1F087;DOMINO TILE VERTICAL-05-01;So;0;ON;;;;;N;;;;;
+1F088;DOMINO TILE VERTICAL-05-02;So;0;ON;;;;;N;;;;;
+1F089;DOMINO TILE VERTICAL-05-03;So;0;ON;;;;;N;;;;;
+1F08A;DOMINO TILE VERTICAL-05-04;So;0;ON;;;;;N;;;;;
+1F08B;DOMINO TILE VERTICAL-05-05;So;0;ON;;;;;N;;;;;
+1F08C;DOMINO TILE VERTICAL-05-06;So;0;ON;;;;;N;;;;;
+1F08D;DOMINO TILE VERTICAL-06-00;So;0;ON;;;;;N;;;;;
+1F08E;DOMINO TILE VERTICAL-06-01;So;0;ON;;;;;N;;;;;
+1F08F;DOMINO TILE VERTICAL-06-02;So;0;ON;;;;;N;;;;;
+1F090;DOMINO TILE VERTICAL-06-03;So;0;ON;;;;;N;;;;;
+1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;;
+1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;;
+1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;;
+1F100;DIGIT ZERO FULL STOP;No;0;EN;<compat> 0030 002E;;0;0;N;;;;;
+1F101;DIGIT ZERO COMMA;No;0;EN;<compat> 0030 002C;;0;0;N;;;;;
+1F102;DIGIT ONE COMMA;No;0;EN;<compat> 0031 002C;;1;1;N;;;;;
+1F103;DIGIT TWO COMMA;No;0;EN;<compat> 0032 002C;;2;2;N;;;;;
+1F104;DIGIT THREE COMMA;No;0;EN;<compat> 0033 002C;;3;3;N;;;;;
+1F105;DIGIT FOUR COMMA;No;0;EN;<compat> 0034 002C;;4;4;N;;;;;
+1F106;DIGIT FIVE COMMA;No;0;EN;<compat> 0035 002C;;5;5;N;;;;;
+1F107;DIGIT SIX COMMA;No;0;EN;<compat> 0036 002C;;6;6;N;;;;;
+1F108;DIGIT SEVEN COMMA;No;0;EN;<compat> 0037 002C;;7;7;N;;;;;
+1F109;DIGIT EIGHT COMMA;No;0;EN;<compat> 0038 002C;;8;8;N;;;;;
+1F10A;DIGIT NINE COMMA;No;0;EN;<compat> 0039 002C;;9;9;N;;;;;
+1F110;PARENTHESIZED LATIN CAPITAL LETTER A;So;0;L;<compat> 0028 0041 0029;;;;N;;;;;
+1F111;PARENTHESIZED LATIN CAPITAL LETTER B;So;0;L;<compat> 0028 0042 0029;;;;N;;;;;
+1F112;PARENTHESIZED LATIN CAPITAL LETTER C;So;0;L;<compat> 0028 0043 0029;;;;N;;;;;
+1F113;PARENTHESIZED LATIN CAPITAL LETTER D;So;0;L;<compat> 0028 0044 0029;;;;N;;;;;
+1F114;PARENTHESIZED LATIN CAPITAL LETTER E;So;0;L;<compat> 0028 0045 0029;;;;N;;;;;
+1F115;PARENTHESIZED LATIN CAPITAL LETTER F;So;0;L;<compat> 0028 0046 0029;;;;N;;;;;
+1F116;PARENTHESIZED LATIN CAPITAL LETTER G;So;0;L;<compat> 0028 0047 0029;;;;N;;;;;
+1F117;PARENTHESIZED LATIN CAPITAL LETTER H;So;0;L;<compat> 0028 0048 0029;;;;N;;;;;
+1F118;PARENTHESIZED LATIN CAPITAL LETTER I;So;0;L;<compat> 0028 0049 0029;;;;N;;;;;
+1F119;PARENTHESIZED LATIN CAPITAL LETTER J;So;0;L;<compat> 0028 004A 0029;;;;N;;;;;
+1F11A;PARENTHESIZED LATIN CAPITAL LETTER K;So;0;L;<compat> 0028 004B 0029;;;;N;;;;;
+1F11B;PARENTHESIZED LATIN CAPITAL LETTER L;So;0;L;<compat> 0028 004C 0029;;;;N;;;;;
+1F11C;PARENTHESIZED LATIN CAPITAL LETTER M;So;0;L;<compat> 0028 004D 0029;;;;N;;;;;
+1F11D;PARENTHESIZED LATIN CAPITAL LETTER N;So;0;L;<compat> 0028 004E 0029;;;;N;;;;;
+1F11E;PARENTHESIZED LATIN CAPITAL LETTER O;So;0;L;<compat> 0028 004F 0029;;;;N;;;;;
+1F11F;PARENTHESIZED LATIN CAPITAL LETTER P;So;0;L;<compat> 0028 0050 0029;;;;N;;;;;
+1F120;PARENTHESIZED LATIN CAPITAL LETTER Q;So;0;L;<compat> 0028 0051 0029;;;;N;;;;;
+1F121;PARENTHESIZED LATIN CAPITAL LETTER R;So;0;L;<compat> 0028 0052 0029;;;;N;;;;;
+1F122;PARENTHESIZED LATIN CAPITAL LETTER S;So;0;L;<compat> 0028 0053 0029;;;;N;;;;;
+1F123;PARENTHESIZED LATIN CAPITAL LETTER T;So;0;L;<compat> 0028 0054 0029;;;;N;;;;;
+1F124;PARENTHESIZED LATIN CAPITAL LETTER U;So;0;L;<compat> 0028 0055 0029;;;;N;;;;;
+1F125;PARENTHESIZED LATIN CAPITAL LETTER V;So;0;L;<compat> 0028 0056 0029;;;;N;;;;;
+1F126;PARENTHESIZED LATIN CAPITAL LETTER W;So;0;L;<compat> 0028 0057 0029;;;;N;;;;;
+1F127;PARENTHESIZED LATIN CAPITAL LETTER X;So;0;L;<compat> 0028 0058 0029;;;;N;;;;;
+1F128;PARENTHESIZED LATIN CAPITAL LETTER Y;So;0;L;<compat> 0028 0059 0029;;;;N;;;;;
+1F129;PARENTHESIZED LATIN CAPITAL LETTER Z;So;0;L;<compat> 0028 005A 0029;;;;N;;;;;
+1F12A;TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S;So;0;L;<compat> 3014 0053 3015;;;;N;;;;;
+1F12B;CIRCLED ITALIC LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;;
+1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;;
+1F12D;CIRCLED CD;So;0;L;<circle> 0043 0044;;;;N;;;;;
+1F12E;CIRCLED WZ;So;0;L;<circle> 0057 005A;;;;N;;;;;
+1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L;<square> 0042;;;;N;;;;;
+1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L;<square> 004E;;;;N;;;;;
+1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L;<square> 0050;;;;N;;;;;
+1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L;<square> 0053;;;;N;;;;;
+1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L;<square> 0057;;;;N;;;;;
+1F14A;SQUARED HV;So;0;L;<square> 0048 0056;;;;N;;;;;
+1F14B;SQUARED MV;So;0;L;<square> 004D 0056;;;;N;;;;;
+1F14C;SQUARED SD;So;0;L;<square> 0053 0044;;;;N;;;;;
+1F14D;SQUARED SS;So;0;L;<square> 0053 0053;;;;N;;;;;
+1F14E;SQUARED PPV;So;0;L;<square> 0050 0050 0056;;;;N;;;;;
+1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;;
+1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;;
+1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;;
+1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;;
+1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;;
+1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;;
+1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;;
+1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;;
+1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;;
+1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;;
+1F190;SQUARE DJ;So;0;L;<square> 0044 004A;;;;N;;;;;
+1F200;SQUARE HIRAGANA HOKA;So;0;L;<square> 307B 304B;;;;N;;;;;
+1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L;<square> 624B;;;;N;;;;;
+1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L;<square> 5B57;;;;N;;;;;
+1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L;<square> 53CC;;;;N;;;;;
+1F213;SQUARED KATAKANA DE;So;0;L;<square> 30C7;;;;N;;;;;
+1F214;SQUARED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<square> 4E8C;;;;N;;;;;
+1F215;SQUARED CJK UNIFIED IDEOGRAPH-591A;So;0;L;<square> 591A;;;;N;;;;;
+1F216;SQUARED CJK UNIFIED IDEOGRAPH-89E3;So;0;L;<square> 89E3;;;;N;;;;;
+1F217;SQUARED CJK UNIFIED IDEOGRAPH-5929;So;0;L;<square> 5929;;;;N;;;;;
+1F218;SQUARED CJK UNIFIED IDEOGRAPH-4EA4;So;0;L;<square> 4EA4;;;;N;;;;;
+1F219;SQUARED CJK UNIFIED IDEOGRAPH-6620;So;0;L;<square> 6620;;;;N;;;;;
+1F21A;SQUARED CJK UNIFIED IDEOGRAPH-7121;So;0;L;<square> 7121;;;;N;;;;;
+1F21B;SQUARED CJK UNIFIED IDEOGRAPH-6599;So;0;L;<square> 6599;;;;N;;;;;
+1F21C;SQUARED CJK UNIFIED IDEOGRAPH-524D;So;0;L;<square> 524D;;;;N;;;;;
+1F21D;SQUARED CJK UNIFIED IDEOGRAPH-5F8C;So;0;L;<square> 5F8C;;;;N;;;;;
+1F21E;SQUARED CJK UNIFIED IDEOGRAPH-518D;So;0;L;<square> 518D;;;;N;;;;;
+1F21F;SQUARED CJK UNIFIED IDEOGRAPH-65B0;So;0;L;<square> 65B0;;;;N;;;;;
+1F220;SQUARED CJK UNIFIED IDEOGRAPH-521D;So;0;L;<square> 521D;;;;N;;;;;
+1F221;SQUARED CJK UNIFIED IDEOGRAPH-7D42;So;0;L;<square> 7D42;;;;N;;;;;
+1F222;SQUARED CJK UNIFIED IDEOGRAPH-751F;So;0;L;<square> 751F;;;;N;;;;;
+1F223;SQUARED CJK UNIFIED IDEOGRAPH-8CA9;So;0;L;<square> 8CA9;;;;N;;;;;
+1F224;SQUARED CJK UNIFIED IDEOGRAPH-58F0;So;0;L;<square> 58F0;;;;N;;;;;
+1F225;SQUARED CJK UNIFIED IDEOGRAPH-5439;So;0;L;<square> 5439;;;;N;;;;;
+1F226;SQUARED CJK UNIFIED IDEOGRAPH-6F14;So;0;L;<square> 6F14;;;;N;;;;;
+1F227;SQUARED CJK UNIFIED IDEOGRAPH-6295;So;0;L;<square> 6295;;;;N;;;;;
+1F228;SQUARED CJK UNIFIED IDEOGRAPH-6355;So;0;L;<square> 6355;;;;N;;;;;
+1F229;SQUARED CJK UNIFIED IDEOGRAPH-4E00;So;0;L;<square> 4E00;;;;N;;;;;
+1F22A;SQUARED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<square> 4E09;;;;N;;;;;
+1F22B;SQUARED CJK UNIFIED IDEOGRAPH-904A;So;0;L;<square> 904A;;;;N;;;;;
+1F22C;SQUARED CJK UNIFIED IDEOGRAPH-5DE6;So;0;L;<square> 5DE6;;;;N;;;;;
+1F22D;SQUARED CJK UNIFIED IDEOGRAPH-4E2D;So;0;L;<square> 4E2D;;;;N;;;;;
+1F22E;SQUARED CJK UNIFIED IDEOGRAPH-53F3;So;0;L;<square> 53F3;;;;N;;;;;
+1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L;<square> 6307;;;;N;;;;;
+1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L;<square> 8D70;;;;N;;;;;
+1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<square> 6253;;;;N;;;;;
+1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L;<compat> 3014 672C 3015;;;;N;;;;;
+1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<compat> 3014 4E09 3015;;;;N;;;;;
+1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<compat> 3014 4E8C 3015;;;;N;;;;;
+1F243;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89;So;0;L;<compat> 3014 5B89 3015;;;;N;;;;;
+1F244;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9;So;0;L;<compat> 3014 70B9 3015;;;;N;;;;;
+1F245;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<compat> 3014 6253 3015;;;;N;;;;;
+1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L;<compat> 3014 76D7 3015;;;;N;;;;;
+1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L;<compat> 3014 52DD 3015;;;;N;;;;;
+1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L;<compat> 3014 6557 3015;;;;N;;;;;
+20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;;
+2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;;
+2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;;
+2B734;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;;
+2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;;
+2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;;
+2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;;
+2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;;
+2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;;
+2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;;
+2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;;
+2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;;
+2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;;
+2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;;
+2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;;
+2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;;
+2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;;
+2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;;
+2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;;
+2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;;
+2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;;
+2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;;
+2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;;
+2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;;
+2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;;
+2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;;
+2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;;
+2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;;
+2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;;
+2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;;
+2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;;
+2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;;
+2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;;
+2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;;
+2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;;
+2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;;
+2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;;
+2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;;
+2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;;
+2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;;
+2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;;
+2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;;
+2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;;
+2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;;
+2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;;
+2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;;
+2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;;
+2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;;
+2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;;
+2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;;
+2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;;
+2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;;
+2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;;
+2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;;
+2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;;
+2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;;
+2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;;
+2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;;
+2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;;
+2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;;
+2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;;
+2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;;
+2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;;
+2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;;
+2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;;
+2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;;
+2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;;
+2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;;
+2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;;
+2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;;
+2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;;
+2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;;
+2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;;
+2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;;
+2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;;
+2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;;
+2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;;
+2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;;
+2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;;
+2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;;
+2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;;
+2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;;
+2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;;
+2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;;
+2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;;
+2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;;
+2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;;
+2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;;
+2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;;
+2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;;
+2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;;
+2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;;
+2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;;
+2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;;
+2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;;
+2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;;
+2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;;
+2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;;
+2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;;
+2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;;
+2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;;
+2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;;
+2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;;
+2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;;
+2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;;
+2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;;
+2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;;
+2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;;
+2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;36FC;;;;N;;;;;
+2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;;
+2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;;
+2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;;
+2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;;
+2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;;
+2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;;
+2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;;
+2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;;
+2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;;
+2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;;
+2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;;
+2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F53;;;;N;;;;;
+2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;;
+2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;;
+2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;;
+2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;;
+2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;;
+2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;;
+2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;;
+2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;;
+2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;;
+2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;;
+2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;;
+2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;;
+2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;;
+2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;;
+2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;;
+2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;;
+2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;;
+2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;;
+2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;;
+2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;;
+2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;;
+2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;;
+2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;;
+2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;;
+2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;;
+2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;;
+2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;;
+2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;9;N;;;;;
+2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;;
+2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;;
+2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;;
+2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;;
+2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;;
+2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;;
+2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;;
+2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;;
+2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;;
+2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;;
+2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;;
+2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;;
+2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;;
+2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;;
+2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;;
+2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;;
+2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;;
+2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;;
+2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;;
+2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;;
+2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;;
+2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;;
+2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;;
+2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;;
+2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;;
+2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;;
+2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;;
+2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;;
+2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;;
+2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;;
+2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;;
+2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;;
+2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;;
+2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;;
+2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;;
+2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;;
+2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;;
+2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;;
+2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;;
+2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;;
+2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;;
+2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;;
+2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;;
+2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;;
+2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;;
+2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;;
+2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;;
+2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;;
+2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;;
+2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;;
+2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;;
+2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;;
+2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;;
+2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;;
+2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;;
+2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;;
+2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;;
+2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;;
+2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;;
+2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;;
+2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;;
+2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;;
+2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;;
+2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;;
+2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;;
+2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;;
+2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;;
+2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;;
+2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;;
+2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;;
+2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;;
+2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;;
+2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;;
+2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;;
+2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;;
+2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;;
+2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;;
+2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;;
+2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;;
+2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;;
+2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;;
+2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;;
+2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;;
+2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;;
+2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;;
+2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;;
+2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;;
+2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;;
+2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;;
+2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;;
+2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;;
+2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;;
+2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;;
+2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;;
+2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;;
+2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;;
+2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;;
+2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;;
+2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;;
+2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;;
+2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;;
+2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;;
+2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;;
+2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;;
+2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;;
+2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;;
+2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;;
+2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;;
+2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;;
+2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;;
+2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;;
+2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;;
+2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;;
+2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;;
+2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;;
+2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;;
+2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;;
+2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;;
+2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;;
+2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;;
+2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;;
+2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;;
+2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;;
+2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;;
+2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;;
+2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;;
+2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;;
+2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;;
+2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;;
+2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;;
+2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;;
+2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;;
+2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;;
+2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;;
+2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;;
+2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;;
+2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;;
+2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;;
+2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;;
+2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;;
+2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;;
+2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;;
+2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;243AB;;;;N;;;;;
+2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;;
+2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;;
+2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;;
+2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;;
+2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;;
+2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;;
+2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;;
+2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;;
+2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;;
+2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;;
+2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;;
+2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;;
+2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;;
+2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;;
+2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;;
+2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;;
+2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;;
+2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;;
+2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;;
+2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;;
+2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;;
+2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;;
+2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;;
+2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;;
+2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;;
+2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;;
+2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;;
+2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;;
+2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;;
+2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;;
+2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;;
+2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;;
+2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;;
+2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;;
+2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;;
+2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;;
+2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;;
+2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;;
+2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;;
+2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;;
+2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;;
+2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;;
+2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;;
+2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;;
+2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;;
+2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;;
+2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;;
+2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;;
+2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;;
+2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;;
+2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;;
+2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;;
+2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;;
+2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;;
+2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;;
+2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;;
+2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;;
+2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;;
+2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;;
+2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;;
+2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;;
+2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;;
+2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;;
+2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AEE;;;;N;;;;;
+2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;;
+2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;;
+2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;;
+2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;;
+2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;;
+2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;;
+2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;;
+2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;;
+2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;;
+2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;;
+2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;;
+2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;;
+2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;;
+2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;;
+2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;;
+2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;;
+2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;;
+2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;;
+2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;;
+2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;;
+2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;;
+2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;;
+2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;;
+2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;;
+2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;;
+2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;;
+2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;;
+2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;;
+2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;;
+2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;;
+2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;;
+2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;;
+2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;;
+2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;;
+2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;;
+2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;;
+2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;;
+2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;;
+2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;;
+2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;;
+2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;;
+2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;;
+2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;;
+2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;;
+2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;;
+2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;;
+2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;;
+2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;;
+2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;;
+2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;;
+2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;;
+2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;;
+2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;;
+2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;;
+2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;;
+2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;;
+2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;;
+2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;;
+2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;;
+2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;;
+2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;;
+2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;;
+2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;;
+2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;;
+2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;;
+2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;;
+2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;;
+2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;;
+2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;;
+2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;;
+2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;;
+2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;;
+2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;;
+2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;;
+2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;;
+2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;;
+2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;;
+2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;;
+2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;;
+2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;;
+2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;;
+2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;;
+2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;;
+2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;;
+2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;;
+2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;;
+2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;;
+2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;;
+2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;;
+2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;;
+2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;;
+2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;;
+2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;;
+2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;;
+2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;;
+2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;45D7;;;;N;;;;;
+2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;;
+2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;;
+2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;;
+2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;;
+2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;;
+2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;;
+2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;;
+2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;;
+2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;;
+2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;;
+2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;;
+2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;;
+2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;;
+2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;;
+2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;;
+2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;;
+2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;;
+2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;;
+2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;;
+2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;;
+2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;;
+2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;;
+2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;;
+2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;;
+2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;;
+2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;;
+2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;;
+2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;;
+2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;;
+2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;;
+2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;;
+2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;;
+2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;;
+2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;;
+2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;;
+2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;;
+2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;;
+2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;;
+2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;;
+2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;;
+2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;;
+2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;;
+2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;;
+2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;;
+2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;;
+2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;;
+2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;;
+2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;;
+2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;;
+2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;;
+2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;;
+2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;;
+2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;;
+2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;;
+2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;;
+2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;;
+2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;;
+2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;;
+2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;;
+2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;;
+2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;;
+2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;;
+2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;;
+2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;;
+2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;;
+2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;;
+2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;;
+2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;;
+2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;;
+2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;;
+2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;;
+2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;;
+2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;;
+2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;;
+2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;;
+2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;;
+2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;;
+2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;;
+2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;;
+2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;;
+2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;;
+2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;;
+2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;;
+2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;;
+2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;;
+2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;;
+2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;;
+2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;;
+2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;;
+2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;;
+2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;;
+2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;;
+2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;;
+2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;;
+E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;;
+E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;;
+E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;;
+E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;;
+E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;;
+E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;;
+E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;;
+E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;;
+E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;;
+E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;;
+E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;;
+E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;;
+E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;;
+E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;;
+E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;;
+E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;;
+E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;;
+E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;;
+E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;;
+E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;;
+E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;;
+E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;;
+E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;;
+E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;;
+E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;;
+E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;;
+E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;;
+E003A;TAG COLON;Cf;0;BN;;;;;N;;;;;
+E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;;
+E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;;
+E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;;
+E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;;
+E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;;
+E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;;
+E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;;
+E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;;
+E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;;
+E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;;
+E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;;
+E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;;
+E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;;
+E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;;
+E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;;
+E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;;
+E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;;
+E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;;
+E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;;
+E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;;
+E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;;
+E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;;
+E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;;
+E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;;
+E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;;
+E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;;
+E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;;
+E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;;
+E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;;
+E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;;
+E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;;
+E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;;
+E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;;
+E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;;
+E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;;
+E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;;
+E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;;
+E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;;
+E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;;
+E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;;
+E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;;
+E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;;
+E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;;
+E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;;
+E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;;
+E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;;
+E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;;
+E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;;
+E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;;
+E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;;
+E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;;
+E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;;
+E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;;
+E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;;
+E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;;
+E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;;
+E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;;
+E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;;
+E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;;
+E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;;
+E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;;
+E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;;
+E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;;
+E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;;
+E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;;
+E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;;
+E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;;
+E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;;
+E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;;
+E0100;VARIATION SELECTOR-17;Mn;0;NSM;;;;;N;;;;;
+E0101;VARIATION SELECTOR-18;Mn;0;NSM;;;;;N;;;;;
+E0102;VARIATION SELECTOR-19;Mn;0;NSM;;;;;N;;;;;
+E0103;VARIATION SELECTOR-20;Mn;0;NSM;;;;;N;;;;;
+E0104;VARIATION SELECTOR-21;Mn;0;NSM;;;;;N;;;;;
+E0105;VARIATION SELECTOR-22;Mn;0;NSM;;;;;N;;;;;
+E0106;VARIATION SELECTOR-23;Mn;0;NSM;;;;;N;;;;;
+E0107;VARIATION SELECTOR-24;Mn;0;NSM;;;;;N;;;;;
+E0108;VARIATION SELECTOR-25;Mn;0;NSM;;;;;N;;;;;
+E0109;VARIATION SELECTOR-26;Mn;0;NSM;;;;;N;;;;;
+E010A;VARIATION SELECTOR-27;Mn;0;NSM;;;;;N;;;;;
+E010B;VARIATION SELECTOR-28;Mn;0;NSM;;;;;N;;;;;
+E010C;VARIATION SELECTOR-29;Mn;0;NSM;;;;;N;;;;;
+E010D;VARIATION SELECTOR-30;Mn;0;NSM;;;;;N;;;;;
+E010E;VARIATION SELECTOR-31;Mn;0;NSM;;;;;N;;;;;
+E010F;VARIATION SELECTOR-32;Mn;0;NSM;;;;;N;;;;;
+E0110;VARIATION SELECTOR-33;Mn;0;NSM;;;;;N;;;;;
+E0111;VARIATION SELECTOR-34;Mn;0;NSM;;;;;N;;;;;
+E0112;VARIATION SELECTOR-35;Mn;0;NSM;;;;;N;;;;;
+E0113;VARIATION SELECTOR-36;Mn;0;NSM;;;;;N;;;;;
+E0114;VARIATION SELECTOR-37;Mn;0;NSM;;;;;N;;;;;
+E0115;VARIATION SELECTOR-38;Mn;0;NSM;;;;;N;;;;;
+E0116;VARIATION SELECTOR-39;Mn;0;NSM;;;;;N;;;;;
+E0117;VARIATION SELECTOR-40;Mn;0;NSM;;;;;N;;;;;
+E0118;VARIATION SELECTOR-41;Mn;0;NSM;;;;;N;;;;;
+E0119;VARIATION SELECTOR-42;Mn;0;NSM;;;;;N;;;;;
+E011A;VARIATION SELECTOR-43;Mn;0;NSM;;;;;N;;;;;
+E011B;VARIATION SELECTOR-44;Mn;0;NSM;;;;;N;;;;;
+E011C;VARIATION SELECTOR-45;Mn;0;NSM;;;;;N;;;;;
+E011D;VARIATION SELECTOR-46;Mn;0;NSM;;;;;N;;;;;
+E011E;VARIATION SELECTOR-47;Mn;0;NSM;;;;;N;;;;;
+E011F;VARIATION SELECTOR-48;Mn;0;NSM;;;;;N;;;;;
+E0120;VARIATION SELECTOR-49;Mn;0;NSM;;;;;N;;;;;
+E0121;VARIATION SELECTOR-50;Mn;0;NSM;;;;;N;;;;;
+E0122;VARIATION SELECTOR-51;Mn;0;NSM;;;;;N;;;;;
+E0123;VARIATION SELECTOR-52;Mn;0;NSM;;;;;N;;;;;
+E0124;VARIATION SELECTOR-53;Mn;0;NSM;;;;;N;;;;;
+E0125;VARIATION SELECTOR-54;Mn;0;NSM;;;;;N;;;;;
+E0126;VARIATION SELECTOR-55;Mn;0;NSM;;;;;N;;;;;
+E0127;VARIATION SELECTOR-56;Mn;0;NSM;;;;;N;;;;;
+E0128;VARIATION SELECTOR-57;Mn;0;NSM;;;;;N;;;;;
+E0129;VARIATION SELECTOR-58;Mn;0;NSM;;;;;N;;;;;
+E012A;VARIATION SELECTOR-59;Mn;0;NSM;;;;;N;;;;;
+E012B;VARIATION SELECTOR-60;Mn;0;NSM;;;;;N;;;;;
+E012C;VARIATION SELECTOR-61;Mn;0;NSM;;;;;N;;;;;
+E012D;VARIATION SELECTOR-62;Mn;0;NSM;;;;;N;;;;;
+E012E;VARIATION SELECTOR-63;Mn;0;NSM;;;;;N;;;;;
+E012F;VARIATION SELECTOR-64;Mn;0;NSM;;;;;N;;;;;
+E0130;VARIATION SELECTOR-65;Mn;0;NSM;;;;;N;;;;;
+E0131;VARIATION SELECTOR-66;Mn;0;NSM;;;;;N;;;;;
+E0132;VARIATION SELECTOR-67;Mn;0;NSM;;;;;N;;;;;
+E0133;VARIATION SELECTOR-68;Mn;0;NSM;;;;;N;;;;;
+E0134;VARIATION SELECTOR-69;Mn;0;NSM;;;;;N;;;;;
+E0135;VARIATION SELECTOR-70;Mn;0;NSM;;;;;N;;;;;
+E0136;VARIATION SELECTOR-71;Mn;0;NSM;;;;;N;;;;;
+E0137;VARIATION SELECTOR-72;Mn;0;NSM;;;;;N;;;;;
+E0138;VARIATION SELECTOR-73;Mn;0;NSM;;;;;N;;;;;
+E0139;VARIATION SELECTOR-74;Mn;0;NSM;;;;;N;;;;;
+E013A;VARIATION SELECTOR-75;Mn;0;NSM;;;;;N;;;;;
+E013B;VARIATION SELECTOR-76;Mn;0;NSM;;;;;N;;;;;
+E013C;VARIATION SELECTOR-77;Mn;0;NSM;;;;;N;;;;;
+E013D;VARIATION SELECTOR-78;Mn;0;NSM;;;;;N;;;;;
+E013E;VARIATION SELECTOR-79;Mn;0;NSM;;;;;N;;;;;
+E013F;VARIATION SELECTOR-80;Mn;0;NSM;;;;;N;;;;;
+E0140;VARIATION SELECTOR-81;Mn;0;NSM;;;;;N;;;;;
+E0141;VARIATION SELECTOR-82;Mn;0;NSM;;;;;N;;;;;
+E0142;VARIATION SELECTOR-83;Mn;0;NSM;;;;;N;;;;;
+E0143;VARIATION SELECTOR-84;Mn;0;NSM;;;;;N;;;;;
+E0144;VARIATION SELECTOR-85;Mn;0;NSM;;;;;N;;;;;
+E0145;VARIATION SELECTOR-86;Mn;0;NSM;;;;;N;;;;;
+E0146;VARIATION SELECTOR-87;Mn;0;NSM;;;;;N;;;;;
+E0147;VARIATION SELECTOR-88;Mn;0;NSM;;;;;N;;;;;
+E0148;VARIATION SELECTOR-89;Mn;0;NSM;;;;;N;;;;;
+E0149;VARIATION SELECTOR-90;Mn;0;NSM;;;;;N;;;;;
+E014A;VARIATION SELECTOR-91;Mn;0;NSM;;;;;N;;;;;
+E014B;VARIATION SELECTOR-92;Mn;0;NSM;;;;;N;;;;;
+E014C;VARIATION SELECTOR-93;Mn;0;NSM;;;;;N;;;;;
+E014D;VARIATION SELECTOR-94;Mn;0;NSM;;;;;N;;;;;
+E014E;VARIATION SELECTOR-95;Mn;0;NSM;;;;;N;;;;;
+E014F;VARIATION SELECTOR-96;Mn;0;NSM;;;;;N;;;;;
+E0150;VARIATION SELECTOR-97;Mn;0;NSM;;;;;N;;;;;
+E0151;VARIATION SELECTOR-98;Mn;0;NSM;;;;;N;;;;;
+E0152;VARIATION SELECTOR-99;Mn;0;NSM;;;;;N;;;;;
+E0153;VARIATION SELECTOR-100;Mn;0;NSM;;;;;N;;;;;
+E0154;VARIATION SELECTOR-101;Mn;0;NSM;;;;;N;;;;;
+E0155;VARIATION SELECTOR-102;Mn;0;NSM;;;;;N;;;;;
+E0156;VARIATION SELECTOR-103;Mn;0;NSM;;;;;N;;;;;
+E0157;VARIATION SELECTOR-104;Mn;0;NSM;;;;;N;;;;;
+E0158;VARIATION SELECTOR-105;Mn;0;NSM;;;;;N;;;;;
+E0159;VARIATION SELECTOR-106;Mn;0;NSM;;;;;N;;;;;
+E015A;VARIATION SELECTOR-107;Mn;0;NSM;;;;;N;;;;;
+E015B;VARIATION SELECTOR-108;Mn;0;NSM;;;;;N;;;;;
+E015C;VARIATION SELECTOR-109;Mn;0;NSM;;;;;N;;;;;
+E015D;VARIATION SELECTOR-110;Mn;0;NSM;;;;;N;;;;;
+E015E;VARIATION SELECTOR-111;Mn;0;NSM;;;;;N;;;;;
+E015F;VARIATION SELECTOR-112;Mn;0;NSM;;;;;N;;;;;
+E0160;VARIATION SELECTOR-113;Mn;0;NSM;;;;;N;;;;;
+E0161;VARIATION SELECTOR-114;Mn;0;NSM;;;;;N;;;;;
+E0162;VARIATION SELECTOR-115;Mn;0;NSM;;;;;N;;;;;
+E0163;VARIATION SELECTOR-116;Mn;0;NSM;;;;;N;;;;;
+E0164;VARIATION SELECTOR-117;Mn;0;NSM;;;;;N;;;;;
+E0165;VARIATION SELECTOR-118;Mn;0;NSM;;;;;N;;;;;
+E0166;VARIATION SELECTOR-119;Mn;0;NSM;;;;;N;;;;;
+E0167;VARIATION SELECTOR-120;Mn;0;NSM;;;;;N;;;;;
+E0168;VARIATION SELECTOR-121;Mn;0;NSM;;;;;N;;;;;
+E0169;VARIATION SELECTOR-122;Mn;0;NSM;;;;;N;;;;;
+E016A;VARIATION SELECTOR-123;Mn;0;NSM;;;;;N;;;;;
+E016B;VARIATION SELECTOR-124;Mn;0;NSM;;;;;N;;;;;
+E016C;VARIATION SELECTOR-125;Mn;0;NSM;;;;;N;;;;;
+E016D;VARIATION SELECTOR-126;Mn;0;NSM;;;;;N;;;;;
+E016E;VARIATION SELECTOR-127;Mn;0;NSM;;;;;N;;;;;
+E016F;VARIATION SELECTOR-128;Mn;0;NSM;;;;;N;;;;;
+E0170;VARIATION SELECTOR-129;Mn;0;NSM;;;;;N;;;;;
+E0171;VARIATION SELECTOR-130;Mn;0;NSM;;;;;N;;;;;
+E0172;VARIATION SELECTOR-131;Mn;0;NSM;;;;;N;;;;;
+E0173;VARIATION SELECTOR-132;Mn;0;NSM;;;;;N;;;;;
+E0174;VARIATION SELECTOR-133;Mn;0;NSM;;;;;N;;;;;
+E0175;VARIATION SELECTOR-134;Mn;0;NSM;;;;;N;;;;;
+E0176;VARIATION SELECTOR-135;Mn;0;NSM;;;;;N;;;;;
+E0177;VARIATION SELECTOR-136;Mn;0;NSM;;;;;N;;;;;
+E0178;VARIATION SELECTOR-137;Mn;0;NSM;;;;;N;;;;;
+E0179;VARIATION SELECTOR-138;Mn;0;NSM;;;;;N;;;;;
+E017A;VARIATION SELECTOR-139;Mn;0;NSM;;;;;N;;;;;
+E017B;VARIATION SELECTOR-140;Mn;0;NSM;;;;;N;;;;;
+E017C;VARIATION SELECTOR-141;Mn;0;NSM;;;;;N;;;;;
+E017D;VARIATION SELECTOR-142;Mn;0;NSM;;;;;N;;;;;
+E017E;VARIATION SELECTOR-143;Mn;0;NSM;;;;;N;;;;;
+E017F;VARIATION SELECTOR-144;Mn;0;NSM;;;;;N;;;;;
+E0180;VARIATION SELECTOR-145;Mn;0;NSM;;;;;N;;;;;
+E0181;VARIATION SELECTOR-146;Mn;0;NSM;;;;;N;;;;;
+E0182;VARIATION SELECTOR-147;Mn;0;NSM;;;;;N;;;;;
+E0183;VARIATION SELECTOR-148;Mn;0;NSM;;;;;N;;;;;
+E0184;VARIATION SELECTOR-149;Mn;0;NSM;;;;;N;;;;;
+E0185;VARIATION SELECTOR-150;Mn;0;NSM;;;;;N;;;;;
+E0186;VARIATION SELECTOR-151;Mn;0;NSM;;;;;N;;;;;
+E0187;VARIATION SELECTOR-152;Mn;0;NSM;;;;;N;;;;;
+E0188;VARIATION SELECTOR-153;Mn;0;NSM;;;;;N;;;;;
+E0189;VARIATION SELECTOR-154;Mn;0;NSM;;;;;N;;;;;
+E018A;VARIATION SELECTOR-155;Mn;0;NSM;;;;;N;;;;;
+E018B;VARIATION SELECTOR-156;Mn;0;NSM;;;;;N;;;;;
+E018C;VARIATION SELECTOR-157;Mn;0;NSM;;;;;N;;;;;
+E018D;VARIATION SELECTOR-158;Mn;0;NSM;;;;;N;;;;;
+E018E;VARIATION SELECTOR-159;Mn;0;NSM;;;;;N;;;;;
+E018F;VARIATION SELECTOR-160;Mn;0;NSM;;;;;N;;;;;
+E0190;VARIATION SELECTOR-161;Mn;0;NSM;;;;;N;;;;;
+E0191;VARIATION SELECTOR-162;Mn;0;NSM;;;;;N;;;;;
+E0192;VARIATION SELECTOR-163;Mn;0;NSM;;;;;N;;;;;
+E0193;VARIATION SELECTOR-164;Mn;0;NSM;;;;;N;;;;;
+E0194;VARIATION SELECTOR-165;Mn;0;NSM;;;;;N;;;;;
+E0195;VARIATION SELECTOR-166;Mn;0;NSM;;;;;N;;;;;
+E0196;VARIATION SELECTOR-167;Mn;0;NSM;;;;;N;;;;;
+E0197;VARIATION SELECTOR-168;Mn;0;NSM;;;;;N;;;;;
+E0198;VARIATION SELECTOR-169;Mn;0;NSM;;;;;N;;;;;
+E0199;VARIATION SELECTOR-170;Mn;0;NSM;;;;;N;;;;;
+E019A;VARIATION SELECTOR-171;Mn;0;NSM;;;;;N;;;;;
+E019B;VARIATION SELECTOR-172;Mn;0;NSM;;;;;N;;;;;
+E019C;VARIATION SELECTOR-173;Mn;0;NSM;;;;;N;;;;;
+E019D;VARIATION SELECTOR-174;Mn;0;NSM;;;;;N;;;;;
+E019E;VARIATION SELECTOR-175;Mn;0;NSM;;;;;N;;;;;
+E019F;VARIATION SELECTOR-176;Mn;0;NSM;;;;;N;;;;;
+E01A0;VARIATION SELECTOR-177;Mn;0;NSM;;;;;N;;;;;
+E01A1;VARIATION SELECTOR-178;Mn;0;NSM;;;;;N;;;;;
+E01A2;VARIATION SELECTOR-179;Mn;0;NSM;;;;;N;;;;;
+E01A3;VARIATION SELECTOR-180;Mn;0;NSM;;;;;N;;;;;
+E01A4;VARIATION SELECTOR-181;Mn;0;NSM;;;;;N;;;;;
+E01A5;VARIATION SELECTOR-182;Mn;0;NSM;;;;;N;;;;;
+E01A6;VARIATION SELECTOR-183;Mn;0;NSM;;;;;N;;;;;
+E01A7;VARIATION SELECTOR-184;Mn;0;NSM;;;;;N;;;;;
+E01A8;VARIATION SELECTOR-185;Mn;0;NSM;;;;;N;;;;;
+E01A9;VARIATION SELECTOR-186;Mn;0;NSM;;;;;N;;;;;
+E01AA;VARIATION SELECTOR-187;Mn;0;NSM;;;;;N;;;;;
+E01AB;VARIATION SELECTOR-188;Mn;0;NSM;;;;;N;;;;;
+E01AC;VARIATION SELECTOR-189;Mn;0;NSM;;;;;N;;;;;
+E01AD;VARIATION SELECTOR-190;Mn;0;NSM;;;;;N;;;;;
+E01AE;VARIATION SELECTOR-191;Mn;0;NSM;;;;;N;;;;;
+E01AF;VARIATION SELECTOR-192;Mn;0;NSM;;;;;N;;;;;
+E01B0;VARIATION SELECTOR-193;Mn;0;NSM;;;;;N;;;;;
+E01B1;VARIATION SELECTOR-194;Mn;0;NSM;;;;;N;;;;;
+E01B2;VARIATION SELECTOR-195;Mn;0;NSM;;;;;N;;;;;
+E01B3;VARIATION SELECTOR-196;Mn;0;NSM;;;;;N;;;;;
+E01B4;VARIATION SELECTOR-197;Mn;0;NSM;;;;;N;;;;;
+E01B5;VARIATION SELECTOR-198;Mn;0;NSM;;;;;N;;;;;
+E01B6;VARIATION SELECTOR-199;Mn;0;NSM;;;;;N;;;;;
+E01B7;VARIATION SELECTOR-200;Mn;0;NSM;;;;;N;;;;;
+E01B8;VARIATION SELECTOR-201;Mn;0;NSM;;;;;N;;;;;
+E01B9;VARIATION SELECTOR-202;Mn;0;NSM;;;;;N;;;;;
+E01BA;VARIATION SELECTOR-203;Mn;0;NSM;;;;;N;;;;;
+E01BB;VARIATION SELECTOR-204;Mn;0;NSM;;;;;N;;;;;
+E01BC;VARIATION SELECTOR-205;Mn;0;NSM;;;;;N;;;;;
+E01BD;VARIATION SELECTOR-206;Mn;0;NSM;;;;;N;;;;;
+E01BE;VARIATION SELECTOR-207;Mn;0;NSM;;;;;N;;;;;
+E01BF;VARIATION SELECTOR-208;Mn;0;NSM;;;;;N;;;;;
+E01C0;VARIATION SELECTOR-209;Mn;0;NSM;;;;;N;;;;;
+E01C1;VARIATION SELECTOR-210;Mn;0;NSM;;;;;N;;;;;
+E01C2;VARIATION SELECTOR-211;Mn;0;NSM;;;;;N;;;;;
+E01C3;VARIATION SELECTOR-212;Mn;0;NSM;;;;;N;;;;;
+E01C4;VARIATION SELECTOR-213;Mn;0;NSM;;;;;N;;;;;
+E01C5;VARIATION SELECTOR-214;Mn;0;NSM;;;;;N;;;;;
+E01C6;VARIATION SELECTOR-215;Mn;0;NSM;;;;;N;;;;;
+E01C7;VARIATION SELECTOR-216;Mn;0;NSM;;;;;N;;;;;
+E01C8;VARIATION SELECTOR-217;Mn;0;NSM;;;;;N;;;;;
+E01C9;VARIATION SELECTOR-218;Mn;0;NSM;;;;;N;;;;;
+E01CA;VARIATION SELECTOR-219;Mn;0;NSM;;;;;N;;;;;
+E01CB;VARIATION SELECTOR-220;Mn;0;NSM;;;;;N;;;;;
+E01CC;VARIATION SELECTOR-221;Mn;0;NSM;;;;;N;;;;;
+E01CD;VARIATION SELECTOR-222;Mn;0;NSM;;;;;N;;;;;
+E01CE;VARIATION SELECTOR-223;Mn;0;NSM;;;;;N;;;;;
+E01CF;VARIATION SELECTOR-224;Mn;0;NSM;;;;;N;;;;;
+E01D0;VARIATION SELECTOR-225;Mn;0;NSM;;;;;N;;;;;
+E01D1;VARIATION SELECTOR-226;Mn;0;NSM;;;;;N;;;;;
+E01D2;VARIATION SELECTOR-227;Mn;0;NSM;;;;;N;;;;;
+E01D3;VARIATION SELECTOR-228;Mn;0;NSM;;;;;N;;;;;
+E01D4;VARIATION SELECTOR-229;Mn;0;NSM;;;;;N;;;;;
+E01D5;VARIATION SELECTOR-230;Mn;0;NSM;;;;;N;;;;;
+E01D6;VARIATION SELECTOR-231;Mn;0;NSM;;;;;N;;;;;
+E01D7;VARIATION SELECTOR-232;Mn;0;NSM;;;;;N;;;;;
+E01D8;VARIATION SELECTOR-233;Mn;0;NSM;;;;;N;;;;;
+E01D9;VARIATION SELECTOR-234;Mn;0;NSM;;;;;N;;;;;
+E01DA;VARIATION SELECTOR-235;Mn;0;NSM;;;;;N;;;;;
+E01DB;VARIATION SELECTOR-236;Mn;0;NSM;;;;;N;;;;;
+E01DC;VARIATION SELECTOR-237;Mn;0;NSM;;;;;N;;;;;
+E01DD;VARIATION SELECTOR-238;Mn;0;NSM;;;;;N;;;;;
+E01DE;VARIATION SELECTOR-239;Mn;0;NSM;;;;;N;;;;;
+E01DF;VARIATION SELECTOR-240;Mn;0;NSM;;;;;N;;;;;
+E01E0;VARIATION SELECTOR-241;Mn;0;NSM;;;;;N;;;;;
+E01E1;VARIATION SELECTOR-242;Mn;0;NSM;;;;;N;;;;;
+E01E2;VARIATION SELECTOR-243;Mn;0;NSM;;;;;N;;;;;
+E01E3;VARIATION SELECTOR-244;Mn;0;NSM;;;;;N;;;;;
+E01E4;VARIATION SELECTOR-245;Mn;0;NSM;;;;;N;;;;;
+E01E5;VARIATION SELECTOR-246;Mn;0;NSM;;;;;N;;;;;
+E01E6;VARIATION SELECTOR-247;Mn;0;NSM;;;;;N;;;;;
+E01E7;VARIATION SELECTOR-248;Mn;0;NSM;;;;;N;;;;;
+E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;;
+E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;;
+E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;;
+E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;;
+E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;;
+E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;;
+E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;;
+E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;;
+F0000;<Plane 15 Private Use, First>;Co;0;L;;;;;N;;;;;
+FFFFD;<Plane 15 Private Use, Last>;Co;0;L;;;;;N;;;;;
+100000;<Plane 16 Private Use, First>;Co;0;L;;;;;N;;;;;
+10FFFD;<Plane 16 Private Use, Last>;Co;0;L;;;;;N;;;;;
old mode 100644 (file)
new mode 100755 (executable)
index 2cdb85c..645ad12
@@ -1,8 +1,11 @@
 # vim:se syn=tcl:
 #
 
+define JIM_VERSION 75
+
 # Note: modules which support options *must* be included before 'options'
-use cc cc-shared
+use cc cc-shared cc-db cc-lib
+use local
 
 options {
     utf8            => "include support for utf8-encoded strings"
@@ -13,7 +16,9 @@ options {
     maintainer      => {enable the [debug] command and JimPanic}
     full            => "Enable some optional features: ipv6, math, utf8, binary, oo, tree"
     with-jim-shared shared => "build a shared library instead of a static library"
-    jim-regexp      => "use the built-in (Tcl-compatible) regexp, even if POSIX regex is available"
+    jim-regexp=1    => "prefer POSIX regex if over the the built-in (Tcl-compatible) regex"
+    docs=1          => "don't build or install the documentation"
+    random-hash                => "randomise hash tables. more secure but hash table results are not predicable"
     with-jim-ext: {with-ext:"ext1 ext2 ..."} => {
         Specify additional jim extensions to include.
         These are enabled by default:
@@ -25,6 +30,7 @@ options {
         exec      - Tcl-compatible exec command
         file      - Tcl-compatible file command
         glob      - Tcl-compatible glob command
+        history   - Tcl access to interactive history
         readdir   - Required for glob
         package   - Package management with the package command
         load      - Load binary extensions at runtime with load or package
@@ -34,17 +40,17 @@ options {
         stdlib    - Built-in commands including lassign, lambda, alias
         syslog    - System logging with syslog
         tclcompat - Tcl compatible read, gets, puts, parray, case, ...
+        namespace - Tcl compatible namespace support
 
         These are disabled by default:
 
-        nvp       - Name-value pairs C-only API
         oo        - Jim OO extension
         tree      - OO tree structure, similar to tcllib ::struct::tree
         binary    - Tcl-compatible 'binary' command
         readline  - Interface to libreadline
         rlprompt  - Tcl wrapper around the readline extension
         mk        - Interface to Metakit
-        sqlite    - Interface to sqlite
+        tclprefix - Support for the tcl::prefix command
         sqlite3   - Interface to sqlite3
         win32     - Interface to win32
     }
@@ -62,8 +68,17 @@ options {
 
 cc-check-types "long long"
 
-cc-check-includes sys/socket.h netinet/in.h arpa/inet.h netdb.h
-cc-check-includes sys/un.h dlfcn.h unistd.h crt_externs.h
+define CCOPTS ""
+define CXXOPTS ""
+if {[cctest -cflags -fno-unwind-tables]} {
+    define-append CCOPTS -fno-unwind-tables
+}
+if {[cctest -cflags -fno-asynchronous-unwind-tables]} {
+    define-append CCOPTS -fno-asynchronous-unwind-tables
+}
+
+cc-check-includes sys/time.h sys/socket.h netinet/in.h arpa/inet.h netdb.h
+cc-check-includes sys/un.h dlfcn.h unistd.h dirent.h crt_externs.h
 
 define LDLIBS ""
 
@@ -78,16 +93,21 @@ if {[cc-check-function-in-lib socket socket]} {
     define-append LDLIBS [get-define lib_socket]
 }
 
-cc-check-functions ualarm lstat fork vfork system select
-cc-check-functions backtrace geteuid mkstemp realpath strptime gettimeofday
-cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist
+cc-check-functions ualarm lstat fork vfork system select execvpe
+cc-check-functions backtrace geteuid mkstemp realpath strptime isatty
+cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii
 cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes
+cc-check-functions shutdown socketpair isinf isnan
+
 if {[cc-check-functions sysinfo]} {
     cc-with {-includes sys/sysinfo.h} {
         cc-check-members "struct sysinfo.uptime"
     }
 }
 
+cc-check-lfs
+cc-check-functions fseeko ftello
+
 define TCL_LIBRARY [get-define prefix]/lib/jim
 
 lassign [split [get-define host] -] host_cpu host_vendor host_os
@@ -135,22 +155,6 @@ if {[cctest -includes {sys/types.h sys/stat.h} -code {mkdir("/dummy");}]} {
     msg-result no
 }
 
-# autosetup can't handle C++ libraries
-proc check-metakit {} {
-    set found 0
-    cc-with {-lang c++} {
-        msg-checking "Checking for Metakit..."
-        if {[cctest -includes mk4.h -libs -lmk4 -code {c4_Storage dummy();}]} {
-            msg-result ok
-            define lib_mk -lmk4
-            incr found
-        } else {
-            msg-result "not found"
-        }
-    }
-    return $found
-}
-
 set extra_objs {}
 set jimregexp 0
 
@@ -176,7 +180,7 @@ if {[opt-bool ipv6 full]} {
     define JIM_IPV6
 }
 if {[opt-bool lineedit full]} {
-    if {([cc-check-includes termios.h] && [cc-check-functions isatty]) || [have-feature winconsole]} {
+    if {([cc-check-includes termios.h] && [have-feature isatty]) || [have-feature winconsole]} {
         msg-result "Enabling line editing"
         define USE_LINENOISE
         lappend extra_objs linenoise.o
@@ -192,191 +196,118 @@ if {[opt-bool shared with-jim-shared]} {
     msg-result "Building static library"
     define JIM_STATICLIB
 }
+define LIBSOEXT [format [get-define SH_SOEXTVER] [format %.2f [expr {[get-define JIM_VERSION] / 100.0}]]]
 define JIM_INSTALL [opt-bool install-jim]
-
-# Note: Extension handling is mapped directly from the configure.ac
-# implementation
-
-set without [join [opt-val {without-ext with-out-jim-ext}]]
-set withext [join [opt-val {with-ext with-jim-ext}]]
-set withmod [join [opt-val {with-mod with-jim-extmod}]]
-
-# Tcl extensions
-set ext_tcl "stdlib glob tclcompat tree rlprompt oo binary"
-# Native extensions
-set ext_c "load package readdir array clock exec file posix regexp signal aio eventloop pack syslog nvp readline mk sqlite sqlite3 win32 sdl"
-
-# C++ extensions
-set ext_cxx "mk"
-
-# Tcl extensions which can be modules
-set ext_tcl_mod "glob tree rlprompt oo binary"
-# Native extensions which can be modules
-set ext_c_mod "readdir array clock file posix regexp syslog readline pack mk sqlite sqlite3 win32 sdl"
-
-# All extensions
-set ext_all [concat $ext_c $ext_tcl]
-
-# Default static extensions
-set ext_default "stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio eventloop syslog"
-
-if {[opt-bool full]} {
-    lappend ext_default tree binary
+define JIM_DOCS [opt-bool docs]
+define JIM_RANDOMISE_HASH [opt-bool random-hash]
+
+# Attributes of the extensions
+# tcl=Pure Tcl extension
+# static=Can't be built as a module
+# optional=Not selected by default
+# cpp=Is a C++ extension
+global extdb
+dict set extdb attrs {
+    aio       { static }
+    array     {}
+    binary    { tcl }
+    clock     {}
+    eventloop { static }
+    exec      { static }
+    file      {}
+    glob      { tcl }
+    history   {}
+    load      { static }
+    mk        { cpp optional }
+    namespace { static }
+    nshelper  { tcl optional }
+    oo        { tcl }
+    pack      {}
+    package   { static }
+    posix     {}
+    readdir   {}
+    readline  { optional }
+    regexp    {}
+    rlprompt  { tcl optional }
+    sdl       { optional }
+    signal    { static }
+    sqlite3   { optional }
+    stdlib    { tcl static }
+    syslog    {}
+    tclcompat { tcl static }
+    tclprefix {}
+    tree      { tcl }
+    win32     { optional }
 }
 
-if {$without eq "default"} {
-    set ext_default stdlib
-    set without {}
+# Additional information about certain extensions
+# dep=list of extensions which are required for this extension
+# check=[expr] expression to evaluate to determine if the extension can be used
+# libdep=list of 'define' symbols for dependent libraries
+dict set extdb info {
+    binary   { dep pack }
+    exec     { check {([have-feature vfork] && [have-feature waitpid]) || [have-feature system]} }
+    glob     { dep readdir }
+    load     { check {[have-feature dlopen-compat] || [cc-check-function-in-lib dlopen dl]} libdep lib_dlopen }
+    mk       { check {[check-metakit]} libdep lib_mk }
+    namespace { dep nshelper }
+    posix    { check {[have-feature waitpid]} }
+    readdir  { check {[have-feature opendir]} }
+    readline { check {[cc-check-function-in-lib readline readline]} libdep lib_readline}
+    rlprompt { dep readline }
+    tree     { dep oo }
+    sdl      { check {[cc-check-function-in-lib SDL_SetVideoMode SDL] && [cc-check-function-in-lib rectangleRGBA SDL_gfx]}
+               libdep {lib_SDL_SetVideoMode lib_rectangleRGBA}
+             }
+    signal   { check {[have-feature sigaction] && [have-feature vfork]} }
+    sqlite3  { check {[cc-check-function-in-lib sqlite3_prepare_v2 sqlite3]} libdep lib_sqlite3_prepare_v2 }
+    syslog   { check {[have-feature syslog]} }
+    tree     { dep oo }
+    win32    { check {[have-feature windows]} }
 }
 
-# Check valid extension names
-foreach i [concat $withext $without $withmod] {
-    if {$i ni $ext_all} {
-        user-error "Unknown extension: $i"
-    }
-}
-
-# needs_xxx="expression" means that the expr must eval to 1 to select the extension
-# dep_xxx="yyy zzz" means that if xxx is selected, so is yyy and zzz
-set dep(glob) readdir
-set dep(rlprompt) readline
-set dep(tree) oo
-set dep(binary) pack
-
-set needs(exec) {expr {([have-feature vfork] && [have-feature waitpid]) || [have-feature system]}}
-set needs(load) {expr {[cc-check-function-in-lib dlopen dl] || [have-feature dlopen-compat]}}
-set libdep(load) lib_dlopen
-set needs(posix) {have-feature waitpid}
-set needs(readdir) {have-feature opendir}
-set needs(readline) {cc-check-function-in-lib readline readline}
-set libdep(readline) lib_readline
-set needs(signal) {expr {[have-feature sigaction] && [have-feature vfork]}}
-set needs(mk) {check-metakit}
-set libdep(mk) lib_mk
-set needs(sqlite) {cc-check-function-in-lib sqlite_open sqlite}
-set libdep(sqlite) lib_sqlite_open
-set needs(sqlite3) {cc-check-function-in-lib sqlite3_open sqlite3}
-set libdep(sqlite3) lib_sqlite3_open
-set needs(syslog) {have-feature syslog}
-set needs(win32) {have-feature windows}
-set needs(sdl) {expr {[cc-check-function-in-lib SDL_SetVideoMode SDL] && [cc-check-function-in-lib rectangleRGBA SDL_gfx]}}
-set libdep(sdl) {lib_SDL_SetVideoMode lib_rectangleRGBA}
-
-# First handle dependencies. If an extension is enabled, also enable its dependency
-foreach i [concat $ext_default $withext] {
-    if {$i in $without} {
-        continue
-    }
-    if {[info exists dep($i)]} {
-        lappend withext {*}$dep($i)
-    }
-}
-
-foreach i $withmod {
-    if {[info exists dep($i)]} {
-        # Theoretically, a mod could depend upon something which must be static
-        # If already configured static, don't make it a module
-        foreach d $dep($i) {
-            if {$d ni $withext} {
-                lappend withmod $d
-            }
+# autosetup cc-check-function-in-library can't handle C++ libraries
+proc check-metakit {} {
+    set found 0
+    msg-checking "Checking for Metakit..."
+    cc-with {-lang c++} {
+        if {[cctest -includes mk4.h -libs -lmk4 -code {c4_Storage dummy();}]} {
+            msg-result ok
+            define lib_mk -lmk4
+            incr found
+        } else {
+            msg-result "not found"
         }
     }
+    return $found
 }
 
-# Now that we know what the platform supports:
-
-# For all known extensions:
-# - If it is disabled, remove it
-# - Otherwise, check to see if it's pre-requisites are met
-# -   If yes, add it if it is enabled or is a default
-# -   If no, error if it is enabled, or do nothing otherwise
-# - Modules may be either C or Tcl
-
-set extmodtcl {}
-set extmod {}
-set ext {}
-
-foreach i [lsort $ext_all] {
-    # First discard the extension if disabled or not enabled
-    if {$i in $without} {
-        msg-result "Extension $i...disabled"
-        continue
-    }
-    if {$i ni [concat $withext $withmod $ext_default]} {
-        msg-result "Extension $i...not enabled"
-        continue
-    }
-
-    # Check dependencies
-    set met 1
-    if {[info exists needs($i)]} {
-        set met [eval $needs($i)]
-    }
-
-    define LDLIBS_$i ""
-
-    msg-checking "Extension $i..."
-
-    # Selected as a module?
-    if {$i in $withmod} {
-        if {$i in $ext_tcl_mod} {
-            # Easy, a Tcl module
-            msg-result "tcl"
-            lappend extmodtcl $i
-            continue
-        }
-        if {$i ni $ext_c_mod} {
-            user-error "not a module"
-        }
-        if {!$met} {
-            user-error "dependencies not met"
-        }
-        msg-result "module"
-        lappend extmod $i
-        if {[info exists libdep($i)]} {
-            foreach j $libdep($i) {
-                define-append LDLIBS_$i [get-define $j ""]
-            }
-        }
-        continue
-    }
-
-    # Selected as a static extension?
-    if {$i in $withext} {
-        if {!$met} {
-            user-error "dependencies not met"
-        }
-        msg-result "enabled"
-    } elseif {$i in $ext_default} {
-        if {!$met} {
-            msg-result "disabled (dependencies)"
-            continue
-        }
-        msg-result "enabled (default)"
-    } else {
-        continue
-    }
-
-    lappend ext $i
-    if {[info exists libdep($i)]} {
-        foreach j $libdep($i) {
-            define-append LDLIBS [get-define $j ""]
-        }
-    }
+# Set up the withinfo array based on what the user selected
+global withinfo
+set withinfo(without) [join [opt-val {without-ext with-out-jim-ext}]]
+set withinfo(ext) [join [opt-val {with-ext with-jim-ext}]]
+set withinfo(mod) [join [opt-val {with-mod with-jim-extmod}]]
+set withinfo(nodefault) 0
+if {$withinfo(without) eq "default"} {
+    set withinfo(without) {}
+    set withinfo(nodefault) 1
 }
 
+# Now go check everything - see autosetup/local.tcl
+array set extinfo [check-extensions]
+
+# Now special checks
 if {[have-feature windows]} {
     lappend extra_objs jim-win32compat.o
 
-    if {$extmod ne "" && [get-define JIM_LIBTYPE] eq "static"} {
+    if {[llength $extinfo(module-c)] && [get-define JIM_STATICLIB]} {
         user-error "cygwin/mingw require --shared for dynamic modules"
     }
 }
 
-if {"regexp" in "$ext $extmod"} {
-    # No regcomp means we need to use the built-in version
+if {[ext-get-status regexp] in {y m}} {
     if {![have-feature regcomp]} {
+        # No regcomp means we need to use the built-in version
         incr jimregexp
     }
 }
@@ -387,50 +318,34 @@ if {$jimregexp || [opt-bool jim-regexp]} {
 
     # If the built-in regexp overrides the system regcomp, etc.
     # jim must be built shared so that the correct symbols are found
-    if {"regexp" in $extmod && [get-define JIM_LIBTYPE] eq "static" && [have-feature regcomp]} {
+    if {[ext-get-status regexp] eq "m" && [get-define JIM_STATICLIB] && [have-feature regcomp]} {
         user-error "Must use --shared with regexp module and built-in regexp"
     }
 }
-if {"load" ni $ext} {
+
+if {[ext-get-status load] eq "n"} {
     # If we don't have load, no need to support shared objects
     define SH_LINKFLAGS ""
 }
 
-msg-result "Jim static extensions: [lsort $ext]"
-if {$extmodtcl ne ""} {
-    msg-result "Jim Tcl extensions: [lsort $extmodtcl]"
-}
-if {$extmod ne ""} {
-    msg-result "Jim dynamic extensions: [lsort $extmod]"
+msg-result "Jim static extensions: [lsort [concat $extinfo(static-tcl) $extinfo(static-c)]]"
+if {[llength $extinfo(module-tcl)]} {
+    msg-result "Jim Tcl extensions: [lsort $extinfo(module-tcl)]"
 }
-
-# Separate out the static extensions into C and Tcl
-set ext_static_c {}
-set ext_static_tcl {}
-foreach e $ext {
-    define jim_ext_$e
-    if {$e in $ext_tcl} {
-        lappend ext_static_tcl $e
-    } else {
-        lappend ext_static_c $e
-    }
+if {[llength $extinfo(module-c)]} {
+    msg-result "Jim dynamic extensions: [lsort $extinfo(module-c)]"
 }
 
-# If there are any static C++ extensions, jimsh must be linked using
-# the C++ compiler
-foreach e $ext_static_c {
-    if {$e in $ext_cxx} {
-        define HAVE_CXX_EXTENSIONS
-    }
-}
-
-define STATIC_EXTS [concat $ext_static_c $ext_static_tcl]
-define C_EXT_OBJS [prefix jim- [suffix .o $ext_static_c]]
-define TCL_EXT_OBJS [suffix .o $ext_static_tcl]
-define C_EXT_SHOBJS [suffix .so $extmod]
-define TCL_EXTS [suffix .tcl $extmodtcl]
+define STATIC_EXTS [concat $extinfo(static-c) $extinfo(static-tcl)]
+define C_EXT_OBJS [prefix jim- [suffix .o $extinfo(static-c)]]
+define TCL_EXT_OBJS [suffix .o $extinfo(static-tcl)]
+define C_EXT_SHOBJS [suffix .so $extinfo(module-c)]
+define TCL_EXTS [suffix .tcl $extinfo(module-tcl)]
 define EXTRA_OBJS $extra_objs
 
-make-config-header jim-config.h -auto {HAVE_LONG_LONG* JIM_UTF8} -none *
-make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE_* JIM_*}
+make-config-header jim-config.h -auto {HAVE_LONG_LONG* JIM_UTF8} -bare JIM_VERSION -none *
+make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE_* JIM_* _FILE_OFFSET*}
 make-template Makefile.in
+make-template build-jim-ext.in
+
+catch {exec chmod +x build-jim-ext}
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index c7f69a8..c50bd84
@@ -1 +1 @@
-This is autosetup v0.6.3. See http://msteveb.github.com/autosetup/
+This is autosetup v0.6.5. See http://msteveb.github.com/autosetup/
index b1134c8..18c4218 100755 (executable)
@@ -5,7 +5,7 @@
 # \
 dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@"
 
-set autosetup(version) 0.6.3
+set autosetup(version) 0.6.5
 
 # Can be set to 1 to debug early-init problems
 set autosetup(debug) 0
@@ -87,7 +87,7 @@ proc main {argv} {
                reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
                debug        => "display debugging output as autosetup runs"
                install:=.   => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)"
-               force init   => "create an initial 'configure' script if none exists"
+               force init:=help   => "create initial auto.def, etc.  Use --init=help for known types"
                # Undocumented options
                option-checking=1
                nopager
@@ -119,6 +119,11 @@ proc main {argv} {
                use local
        }
 
+       # Now any auto-load modules
+       foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
+               automf_load source $file
+       }
+
        if {[opt-val help] ne ""} {
                incr autosetup(showhelp)
                use help
@@ -130,9 +135,9 @@ proc main {argv} {
                autosetup_reference [opt-val {manual ref reference}]
        }
 
-       if {[opt-bool init]} {
+       if {[opt-val init] ne ""} {
                use init
-               autosetup_init
+               autosetup_init [opt-val init]
        }
 
        if {[opt-val install] ne ""} {
@@ -143,7 +148,7 @@ proc main {argv} {
        if {![file exists $autosetup(autodef)]} {
                # Check for invalid option first
                options {}
-               user-error "No auto.def found in $autosetup(srcdir)"
+               user-error "No auto.def found in \"$autosetup(srcdir)\" (use [file tail $::autosetup(exe)] --init to create one)"
        }
 
        # Parse extra arguments into autosetup(cmdline)
@@ -167,6 +172,7 @@ proc main {argv} {
        # Log how we were invoked
        configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
 
+       # Note that auto.def is *not* loaded in the global scope
        source $autosetup(autodef)
 
        # Could warn here if options {} was not specified
@@ -174,7 +180,11 @@ proc main {argv} {
        show-notices
 
        if {$autosetup(debug)} {
-               parray define
+               msg-result "Writing all defines to config.log"
+               configlog "================ defines ======================"
+               foreach n [lsort [array names define]] {
+                       configlog "define $n $define($n)"
+               }
        }
 
        exit 0
@@ -421,6 +431,10 @@ proc options {optlist} {
 proc config_guess {} {
        if {[file-isexec $::autosetup(dir)/config.guess]} {
                exec-with-stderr sh $::autosetup(dir)/config.guess
+               if {[catch {exec-with-stderr sh $::autosetup(dir)/config.guess} alias]} {
+                       user-error $alias
+               }
+               return $alias
        } else {
                configlog "No config.guess, so using uname"
                string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r]
@@ -429,10 +443,11 @@ proc config_guess {} {
 
 proc config_sub {alias} {
        if {[file-isexec $::autosetup(dir)/config.sub]} {
-               exec-with-stderr sh $::autosetup(dir)/config.sub $alias
-       } else {
-               return $alias
+               if {[catch {exec-with-stderr sh $::autosetup(dir)/config.sub $alias} alias]} {
+                       user-error $alias
+               }
        }
+       return $alias
 }
 
 # @define name ?value=1?
@@ -754,8 +769,13 @@ proc user-notice {msg} {
 
 # Incorrect usage in the auto.def file. Identify the location.
 proc autosetup-error {msg} {
+       autosetup-full-error [error-location $msg]
+}
+
+# Like autosetup-error, except $msg is the full error message.
+proc autosetup-full-error {msg} {
        show-notices
-       puts stderr [error-location $msg]
+       puts stderr $msg
        exit 1
 }
 
@@ -865,7 +885,14 @@ proc autosetup_add_dep {filename} {
 # @use module ...
 #
 # Load the given library modules.
-# e.g. use cc cc-shared
+# e.g. 'use cc cc-shared'
+#
+# Note that module 'X' is implemented in either 'autosetup/X.tcl'
+# or 'autosetup/X/init.tcl'
+#
+# The latter form is useful for a complex module which requires additional
+# support file. In this form, '$::usedir' is set to the module directory
+# when it is loaded.
 #
 proc use {args} {
        foreach m $args {
@@ -874,20 +901,36 @@ proc use {args} {
                }
                set ::libmodule($m) 1
                if {[info exists ::modsource($m)]} {
-                       uplevel #0 eval $::modsource($m)
+                       automf_load eval $::modsource($m)
                } else {
-                       set source $::autosetup(libdir)/${m}.tcl
-                       if {[file exists $source]} {
-                               uplevel #0 [list source $source]
+                       set sources [list $::autosetup(libdir)/${m}.tcl $::autosetup(libdir)/${m}/init.tcl]
+                       set found 0
+                       foreach source $sources {
+                               if {[file exists $source]} {
+                                       incr found
+                                       break
+                               }
+                       }
+                       if {$found} {
+                               # For the convenience of the "use" source, point to the directory
+                               # it is being loaded from
+                               set ::usedir [file dirname $source]
+                               automf_load source $source
                                autosetup_add_dep $source
                        } else {
-                               puts "Looking for $source"
                                autosetup-error "use: No such module: $m"
                        }
                }
        }
 }
 
+# Load module source in the global scope by executing the given command
+proc automf_load {args} {
+       if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
+               autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
+       }
+}
+
 # Initial settings
 set autosetup(exe) $::argv0
 set autosetup(istcl) 1
@@ -1146,9 +1189,9 @@ proc autosetup_help {what} {
 # If not already paged and stdout is a tty, pipe the output through the pager
 # This is done by reinvoking autosetup with --nopager added
 proc use_pager {} {
-    if {![opt-bool nopager] && [getenv PAGER ""] ne "" && ![string match "not a tty" [exec tty]]} {
+    if {![opt-bool nopager] && [getenv PAGER ""] ne "" && [isatty? stdin] && [isatty? stdout]} {
         catch {
-            exec [info nameofexecutable] $::argv0 --nopager {*}$::argv | [getenv PAGER] >@stdout <@stdin 2>/dev/null
+            exec [info nameofexecutable] $::argv0 --nopager {*}$::argv |& [getenv PAGER] >@stdout <@stdin
         }
         exit 0
     }
@@ -1278,55 +1321,56 @@ set modsource(init) {
 
 # Module to help create auto.def and configure
 
-proc autosetup_init {} {
-       set create_configure 1
-       if {[file exists configure]} {
-               if {!$::autosetup(force)} {
-                       # Could this be an autosetup configure?
-                       if {![string match "*\nWRAPPER=*" [readfile configure]]} {
-                               puts "I see configure, but not created by autosetup, so I won't overwrite it."
-                               puts "Use autosetup --init --force to overwrite."
-                               set create_configure 0
-                       }
-               } else {
-                       puts "I will overwrite the existing configure because you used --force."
+proc autosetup_init {type} {
+       set help 0
+       if {$type in {? help}} {
+               incr help
+       } elseif {![dict exists $::autosetup(inittypes) $type]} {
+               puts "Unknown type, --init=$type"
+               incr help
+       }
+       if {$help} {
+               puts "Use one of the following types (e.g. --init=make)\n"
+               foreach type [lsort [dict keys $::autosetup(inittypes)]] {
+                       lassign [dict get $::autosetup(inittypes) $type] desc
+                       # XXX: Use the options-show code to wrap the description
+                       puts [format "%-10s %s" $type $desc]
                }
-       } else {
-               puts "I don't see configure, so I will create it."
+               exit 0
        }
-       if {$create_configure} {
-               if {!$::autosetup(installed)} {
-                       user-notice "Warning: Initialising from the development version of autosetup"
+       lassign [dict get $::autosetup(inittypes) $type] desc script
 
-                       writefile configure "#!/bin/sh\nWRAPPER=\"\$0\" exec $::autosetup(dir)/autosetup \"\$@\"\n"
-               } else {
-                       writefile configure \
-{#!/bin/sh
-dir="`dirname "$0"`/autosetup"
-WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
-}
-               }
-               catch {exec chmod 755 configure}
-       }
-       if {![file exists auto.def]} {
-               puts "I don't see auto.def, so I will create a default one."
-               writefile auto.def {# Initial auto.def created by 'autosetup --init'
+       puts "Initialising $type: $desc\n"
+
+       # All initialisations happens in the top level srcdir
+       cd $::autosetup(srcdir)
 
-use cc
+       uplevel #0 $script
 
-# Add any user options here
-options {
+       exit 0
 }
 
-make-config-header config.h
-make-template Makefile.in
+proc autosetup_add_init_type {type desc script} {
+       dict set ::autosetup(inittypes) $type [list $desc $script]
 }
-       }
-       if {![file exists Makefile.in]} {
-               puts "Note: I don't see Makefile.in. You will probably need to create one."
-       }
 
-       exit 0
+# This is for in creating build-system init scripts
+#
+# If the file doesn't exist, create it containing $contents
+# If the file does exist, only overwrite if --force is specified.
+#
+proc autosetup_check_create {filename contents} {
+       if {[file exists $filename]} {
+               if {!$::autosetup(force)} {
+                       puts "I see $filename already exists."
+                       return
+               } else {
+                       puts "I will overwrite the existing $filename because you used --force."
+               }
+       } else {
+               puts "I don't see $filename, so I will create it."
+       }
+       writefile $filename $contents
 }
 }
 
@@ -1345,7 +1389,7 @@ proc autosetup_install {dir} {
 
                set f [open autosetup/autosetup w]
 
-               set publicmodules {}
+               set publicmodules $::autosetup(libdir)/default.auto
 
                # First the main script, but only up until "CUT HERE"
                set in [open $::autosetup(dir)/autosetup]
@@ -1393,11 +1437,36 @@ proc autosetup_install {dir} {
                user-error "Failed to install autosetup: $error"
        }
        puts "Installed [autosetup_version] to autosetup/"
-       catch {exec [info nameofexecutable] autosetup/autosetup --init >@stdout 2>@stderr}
+
+       # Now create 'configure' if necessary
+       autosetup_create_configure
 
        exit 0
 }
 
+proc autosetup_create_configure {} {
+       if {[file exists configure]} {
+               if {!$::autosetup(force)} {
+                       # Could this be an autosetup configure?
+                       if {![string match "*\nWRAPPER=*" [readfile configure]]} {
+                               puts "I see configure, but not created by autosetup, so I won't overwrite it."
+                               puts "Remove it or use --force to overwrite."
+                               return
+                       }
+               } else {
+                       puts "I will overwrite the existing configure because you used --force."
+               }
+       } else {
+               puts "I don't see configure, so I will create it."
+       }
+       writefile configure \
+{#!/bin/sh
+dir="`dirname "$0"`/autosetup"
+WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
+}
+       catch {exec chmod 755 configure}
+}
+
 # Append the contents of $file to filehandle $f
 proc autosetup_install_append {f file} {
        set in [open $file]
@@ -1541,15 +1610,28 @@ if {$autosetup(istcl)} {
                }
                return -code error "environment variable \"$name\" does not exist"
        }
-} elseif {$autosetup(iswin)} {
-       # On Windows, backslash convert all environment variables
-       # (Assume that Tcl does this for us)
-       proc getenv {name args} {
-               string map {\\ /} [env $name {*}$args]
+       proc isatty? {channel} {
+               dict exists [fconfigure $channel] -xchar
        }
 } else {
-       # Jim on unix is simple
-       alias getenv env
+       if {$autosetup(iswin)} {
+               # On Windows, backslash convert all environment variables
+               # (Assume that Tcl does this for us)
+               proc getenv {name args} {
+                       string map {\\ /} [env $name {*}$args]
+               }
+       } else {
+               # Jim on unix is simple
+               alias getenv env
+       }
+       proc isatty? {channel} {
+               set tty 0
+               catch {
+                       # isatty is a recent addition to Jim Tcl
+                       set tty [$channel isatty]
+               }
+               return $tty
+       }
 }
 
 # In case 'file normalize' doesn't exist
@@ -1598,46 +1680,59 @@ proc error-location {msg} {
        return $msg
 }
 
-# Similar to error-location, but called when user code generates an error
-# In this case we want to show the stack trace in user code, but not in autosetup code
-# (unless --debug is enabled)
+# If everything is working properly, the only errors which occur
+# should be generated in user code (e.g. auto.def).
+# By default, we only want to show the error location in user code.
+# We use [info frame] to achieve this, but it works differently on Tcl and Jim.
+#
+# This is designed to be called for incorrect usage in auto.def, via autosetup-error
 #
 proc error-stacktrace {msg} {
-       if {$::autosetup(istcl)} {
-               if {[regexp {file "([^ ]*)" line ([0-9]*)} $::errorInfo dummy file line]} {
-                       return "[relative-path $file]:$line $msg\n$::errorInfo"
+       if {$::autosetup(debug)} {
+               return -code error $msg
+       }
+       # Search back through the stack trace for the first error in a .def file
+       for {set i 1} {$i < [info level]} {incr i} {
+               if {$::autosetup(istcl)} {
+                       array set info [info frame -$i]
+               } else {
+                       lassign [info frame -$i] info(caller) info(file) info(line)
                }
-               return $::errorInfo
-       } else {
-               # Prepend a live stacktrace to the error stacktrace, omitting the current level
-               set stacktrace [concat [info stacktrace] [lrange [stacktrace] 3 end]]
-
-               if {!$::autosetup(debug)} {
-                       # Omit any levels from autosetup or with no file
-                       set newstacktrace {}
-                       foreach {p f l} $stacktrace {
-                               if {[string match "*autosetup" $f] || $f eq ""} {
-                                       #puts "Skipping $p $f:$l"
-                                       continue
-                               }
-                               lappend newstacktrace $p $f $l
-                       }
-                       set stacktrace $newstacktrace
+               if {[string match *.def $info(file)]} {
+                       return "[relative-path $info(file)]:$info(line): Error: $msg"
                }
+               #puts "Skipping $info(file):$info(line)"
+       }
+       return $msg
+}
 
-               # Convert filenames to relative paths
-               set newstacktrace {}
-               foreach {p f l} $stacktrace {
-                       lappend newstacktrace $p [relative-path $f] $l
+# Given the return from [catch {...} msg opts], returns an appropriate
+# error message. A nice one for Jim and a less-nice one for Tcl.
+# If 'fulltrace' is set, a full stack trace is provided.
+# Otherwise a simple message is provided.
+#
+# This is designed for developer errors, e.g. in module code or auto.def code
+#
+#
+proc error-dump {msg opts fulltrace} {
+       if {$::autosetup(istcl)} {
+               if {$fulltrace} {
+                       return "Error: [dict get $opts -errorinfo]"
+               } else {
+                       return "Error: $msg"
                }
-               lassign $newstacktrace p f l
+       } else {
+               lassign $opts(-errorinfo) p f l
                if {$f ne ""} {
-                       set prefix "$f:$l: "
-               } else {
-                       set prefix ""
+                       set result "$f:$l: Error: "
+               }
+               append result "$msg\n"
+               if {$fulltrace} {
+                       append result [stackdump $opts(-errorinfo)]
                }
 
-               return "${prefix}Error: $msg\n[stackdump $newstacktrace]"
+               # Remove the trailing newline
+               string trim $result
        }
 }
 }
@@ -1810,10 +1905,10 @@ proc defn {first args} {
 if {$autosetup(debug)} {
        main $argv
 }
-if {[catch {main $argv} msg] == 1} {
+if {[catch {main $argv} msg opts] == 1} {
        show-notices
-       puts stderr [error-stacktrace $msg]
-       if {!$autosetup(debug) && !$autosetup(istcl)} {
+       autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
+       if {!$autosetup(debug)} {
                puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
        }
        exit 1
diff --git a/jim/autosetup/cc-db.tcl b/jim/autosetup/cc-db.tcl
new file mode 100755 (executable)
index 0000000..adaf930
--- /dev/null
@@ -0,0 +1,15 @@
+# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
+# All rights reserved
+
+# @synopsis:
+#
+# The 'cc-db' module provides a knowledge based of system idiosyncracies
+# In general, this module can always be included
+
+use cc
+
+module-options {}
+
+# openbsd needs sys/types.h to detect some system headers
+cc-include-needs sys/socket.h sys/types.h
+cc-include-needs netinet/in.h sys/types.h
old mode 100644 (file)
new mode 100755 (executable)
index e8e5e86..4df5130
@@ -75,3 +75,87 @@ proc cc-check-endian {} {
        }
        return $rc
 }
+
+# @cc-check-flags flag ?...?
+#
+# Checks whether the given C/C++ compiler flags can be used. Defines feature
+# names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and
+# appends working flags to '-cflags' and 'CFLAGS' or 'CXXFLAGS'.
+proc cc-check-flags {args} {
+    set result 1
+    array set opts [cc-get-settings]
+    switch -exact -- $opts(-lang) {
+        c++ {
+            set lang C++
+            set prefix CXXFLAG
+        }
+        c {
+            set lang C
+            set prefix CFLAG
+        }
+        default {
+            autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)"
+        }
+    }
+    foreach flag $args {
+        msg-checking "Checking whether the $lang compiler accepts $flag..."
+        if {[cctest -cflags $flag]} {
+            msg-result yes
+            define-feature $prefix$flag
+            cc-with [list -cflags [list $flag]]
+            define-append ${prefix}S $flag
+        } else {
+            msg-result no
+            set result 0
+        }
+    }
+    return $result
+}
+
+# @cc-check-standards ver ?...?
+#
+# Checks whether the C/C++ compiler accepts one of the specified '-std=$ver'
+# options, and appends the first working one to '-cflags' and 'CFLAGS' or
+# 'CXXFLAGS'.
+proc cc-check-standards {args} {
+    array set opts [cc-get-settings]
+    foreach std $args {
+        if {[cc-check-flags -std=$std]} {
+            return $std
+        }
+    }
+    return ""
+}
+
+# Checks whether $keyword is usable as alignof
+proc cctest_alignof {keyword} {
+    msg-checking "Checking for $keyword..."
+    if {[cctest -code [subst -nobackslashes {
+        printf("minimum alignment is %d == %d\n", ${keyword}(char), ${keyword}('x'));
+    }]]} then {
+        msg-result ok
+        define-feature $keyword
+    } else {
+        msg-result "not found"
+    }
+}
+
+# @cc-check-c11
+#
+# Checks for several C11/C++11 extensions and their alternatives. Currently
+# checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'.
+proc cc-check-c11 {} {
+    msg-checking "Checking for _Static_assert..."
+    if {[cctest -code {
+        _Static_assert(1, "static assertions are available");
+    }]} then {
+        msg-result ok
+        define-feature _Static_assert
+    } else {
+        msg-result "not found"
+    }
+
+    cctest_alignof _Alignof
+    cctest_alignof __alignof__
+    cctest_alignof __alignof
+}
old mode 100644 (file)
new mode 100755 (executable)
index 1e77440..6cfcb50
 # It defines the following variables:
 #
 ## SH_CFLAGS         Flags to use compiling sources destined for a shared library
-## SH_LDFLAGS        Flags to use linking a shared library
+## SH_LDFLAGS        Flags to use linking (creating) a shared library
+## SH_SOPREFIX       Prefix to use to set the soname when creating a shared library
+## SH_SOEXT          Extension for shared libs
+## SH_SOEXTVER       Format for versioned shared libs - %s = version
 ## SHOBJ_CFLAGS      Flags to use compiling sources destined for a shared object
-## SHOBJ_LDFLAGS     Flags to use linking a shared object
+## SHOBJ_LDFLAGS     Flags to use linking a shared object, undefined symbols allowed
+## SHOBJ_LDFLAGS_R   - as above, but all symbols must be resolved
 ## SH_LINKFLAGS      Flags to use linking an executable which will load shared objects
 ## LD_LIBRARY_PATH   Environment variable which specifies path to shared libraries
+## STRIPLIBFLAGS     Arguments to strip to strip a dynamic library
 
 module-options {}
 
-foreach i {SH_LINKFLAGS SH_CFLAGS SH_LDFLAGS SHOBJ_CFLAGS SHOBJ_LDFLAGS} {
-       define $i ""
-}
-
+# Defaults: gcc on unix
+define SHOBJ_CFLAGS -fpic
+define SHOBJ_LDFLAGS -shared
+define SH_CFLAGS -fpic
+define SH_LDFLAGS -shared
+define SH_LINKFLAGS -rdynamic
+define SH_SOEXT .so
+define SH_SOEXTVER .so.%s
+define SH_SOPREFIX -Wl,-soname,
 define LD_LIBRARY_PATH LD_LIBRARY_PATH
+define STRIPLIBFLAGS --strip-unneeded
+
+# Note: This is a helpful reference for identifying the toolchain
+#       http://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers
 
 switch -glob -- [get-define host] {
        *-*-darwin* {
-               define SH_CFLAGS -dynamic
-               define SH_LDFLAGS "-dynamiclib"
                define SHOBJ_CFLAGS "-dynamic -fno-common"
                define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup"
+               define SHOBJ_LDFLAGS_R -bundle
+               define SH_CFLAGS -dynamic
+               define SH_LDFLAGS -dynamiclib
+               define SH_LINKFLAGS ""
+               define SH_SOEXT .dylib
+               define SH_SOEXTVER .%s.dylib
+               define SH_SOPREFIX -Wl,-install_name,
                define LD_LIBRARY_PATH DYLD_LIBRARY_PATH
+               define STRIPLIBFLAGS -x
        }
-       *-*-ming* {
-               define SH_LDFLAGS -shared
+       *-*-ming* - *-*-cygwin - *-*-msys {
+               define SHOBJ_CFLAGS ""
                define SHOBJ_LDFLAGS -shared
-       }
-       *-*-cygwin {
+               define SH_CFLAGS ""
                define SH_LDFLAGS -shared
-               define SHOBJ_LDFLAGS -shared
+               define SH_LINKFLAGS ""
+               define SH_SOEXT .dll
+               define SH_SOEXTVER .dll
+               define SH_SOPREFIX ""
+               define LD_LIBRARY_PATH PATH
+       }
+       sparc* {
+               if {[msg-quiet cc-check-decls __SUNPRO_C]} {
+                       msg-result "Found sun stdio compiler"
+                       # sun stdio compiler
+                       # XXX: These haven't been fully tested. 
+                       define SHOBJ_CFLAGS -KPIC
+                       define SHOBJ_LDFLAGS "-G"
+                       define SH_CFLAGS -KPIC
+                       define SH_LINKFLAGS -Wl,-export-dynamic
+                       define SH_SOPREFIX -Wl,-h,
+               } else {
+                       # sparc has a very small GOT table limit, so use -fPIC
+                       define SH_CFLAGS -fPIC
+                       define SHOBJ_CFLAGS -fPIC
+               }
        }
        *-*-solaris* {
-               # XXX: These haven't been fully tested. 
-               #define SH_LINKFLAGS -Wl,-export-dynamic
-               define SH_CFLAGS -Kpic
-               define SHOBJ_CFLAGS -Kpic
-               define SHOBJ_LDFLAGS "-G"
+               if {[msg-quiet cc-check-decls __SUNPRO_C]} {
+                       msg-result "Found sun stdio compiler"
+                       # sun stdio compiler
+                       # XXX: These haven't been fully tested. 
+                       define SHOBJ_CFLAGS -KPIC
+                       define SHOBJ_LDFLAGS "-G"
+                       define SH_CFLAGS -KPIC
+                       define SH_LINKFLAGS -Wl,-export-dynamic
+                       define SH_SOPREFIX -Wl,-h,
+               }
        }
        *-*-hpux {
                # XXX: These haven't been tested
-               define SH_LINKFLAGS -Wl,+s
-               define SH_CFLAGS +z
                define SHOBJ_CFLAGS "+O3 +z"
                define SHOBJ_LDFLAGS -b
+               define SH_CFLAGS +z
+               define SH_LINKFLAGS -Wl,+s
                define LD_LIBRARY_PATH SHLIB_PATH
        }
-       * {
-               # Generic Unix settings
-               define SH_LINKFLAGS -rdynamic
-               define SH_CFLAGS -fpic
+       *-*-haiku {
+               define SHOBJ_CFLAGS ""
+               define SHOBJ_LDFLAGS -shared
+               define SH_CFLAGS ""
                define SH_LDFLAGS -shared
-               define SHOBJ_CFLAGS -fpic
-               define SHOBJ_LDFLAGS "-shared"
+               define SH_LINKFLAGS ""
+               define SH_SOPREFIX ""
+               define LD_LIBRARY_PATH LIBRARY_PATH
        }
 }
+
+if {![is-defined SHOBJ_LDFLAGS_R]} {
+       define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
+}
old mode 100644 (file)
new mode 100755 (executable)
index 707e69c..bbe7989
@@ -113,7 +113,33 @@ proc cc-check-some-feature {list script} {
 # Checks that the given include files can be used
 proc cc-check-includes {args} {
        cc-check-some-feature $args {
-               cctest -includes $each
+               set with {}
+               if {[dict exists $::autosetup(cc-include-deps) $each]} {
+                       set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
+                       msg-quiet cc-check-includes {*}$deps
+                       foreach i $deps {
+                               if {[have-feature $i]} {
+                                       lappend with $i
+                               }
+                       }
+               }
+               if {[llength $with]} {
+                       cc-with [list -includes $with] {
+                               cctest -includes $each
+                       }
+               } else {
+                       cctest -includes $each
+               }
+       }
+}
+
+# @cc-include-needs include required ...
+#
+# Ensures that when checking for 'include', a check is first
+# made for each 'required' file, and if found, it is #included
+proc cc-include-needs {file args} {
+       foreach depfile $args {
+               dict set ::autosetup(cc-include-deps) $file $depfile 1
        }
 }
 
@@ -232,6 +258,8 @@ proc cc-check-function-in-lib {function libs {otherlibs {}}} {
 # simply "ar" is assumed depending upon whether cross compiling.
 # The path is searched for this executable, and if found AR is defined
 # to the executable name.
+# Note that even when cross compiling, the simple "ar" is used as a fallback,
+# but a warning is generated. This is necessary for some toolchains.
 #
 # It is an error if the executable is not found.
 #
@@ -239,10 +267,16 @@ proc cc-check-tools {args} {
        foreach tool $args {
                set TOOL [string toupper $tool]
                set exe [get-env $TOOL [get-define cross]$tool]
-               if {![find-executable $exe]} {
-                       user-error "Failed to find $exe"
+               if {[find-executable {*}$exe]} {
+                       define $TOOL $exe
+                       continue
+               }
+               if {[find-executable {*}$tool]} {
+                       msg-result "Warning: Failed to find $exe, falling back to $tool which may be incorrect"
+                       define $TOOL $tool
+                       continue
                }
-               define $TOOL $exe
+               user-error "Failed to find $exe"
        }
 }
 
@@ -301,7 +335,7 @@ proc cc-add-settings {settings} {
                                # Note that new libraries are added before previous libraries
                                set new($name) [list {*}$value {*}$new($name)]
                        }
-                       -link - -lang {
+                       -link - -lang - -nooutput {
                                set new($name) $value
                        }
                        -source - -sourcefile - -code {
@@ -374,7 +408,7 @@ proc cc-with {settings args} {
                set rc [catch {uplevel 1 [lindex $args 0]} result info]
                cc-store-settings $save
                if {$rc != 0} {
-                       return $result -code [dict get $info -code]
+                       return -code [dict get $info -code] $result
                }
                return $result
        }
@@ -396,6 +430,7 @@ proc cc-with {settings args} {
 ## -code code          Code to compile in the body of main()
 ## -source code        Compile a complete program. Ignore -includes, -declare and -code
 ## -sourcefile file    Shorthand for -source [readfile [get-define srcdir]/$file]
+## -nooutput 1         Treat any compiler output (e.g. a warning) as an error
 #
 # Unless -source or -sourcefile is specified, the C program looks like:
 #
@@ -467,14 +502,8 @@ proc cctest {args} {
                set tmp conftest__.o
                lappend cmdline -c
        }
-       lappend cmdline {*}$opts(-cflags)
+       lappend cmdline {*}$opts(-cflags) {*}[get-define cc-default-debug ""]
 
-       switch -glob -- [get-define host] {
-               *-*-darwin* {
-                       # Don't generate .dSYM directories
-                       lappend cmdline -gstabs
-               }
-       }
        lappend cmdline $src -o $tmp {*}$opts(-libs)
 
        # At this point we have the complete command line and the
@@ -495,7 +524,8 @@ proc cctest {args} {
        writefile $src $lines\n
 
        set ok 1
-       if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} {
+       set err [catch {exec-with-stderr {*}$cmdline} result errinfo]
+       if {$err || ($opts(-nooutput) && [string length $result])} {
                configlog "Failed: [join $cmdline]"
                configlog $result
                configlog "============"
@@ -565,7 +595,7 @@ proc make-config-header {file args} {
                                continue
                        }
                        -str {
-                               set value \"$value\"
+                               set value \"[string map [list \\ \\\\ \" \\\"] $value]\"
                        }
                        -auto {
                                # Automatically determine the type
@@ -574,7 +604,7 @@ proc make-config-header {file args} {
                                        continue
                                }
                                if {![string is integer -strict $value]} {
-                                       set value \"$value\"
+                                       set value \"[string map [list \\ \\\\ \" \\\"] $value]\"
                                }
                        }
                        "" {
@@ -635,8 +665,6 @@ if {[env-is-set CXX]} {
 # CXXFLAGS default to CFLAGS if not specified
 define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
 
-cc-check-tools ld
-
 # May need a CC_FOR_BUILD, so look for one
 define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
 
@@ -647,7 +675,8 @@ if {[get-define CC] eq ""} {
 define CCACHE [find-an-executable [get-env CCACHE ccache]]
 
 # Initial cctest settings
-cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {}}
+cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
+set autosetup(cc-include-deps) {}
 
 msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]"
 if {[get-define CXX] ne "false"} {
@@ -655,6 +684,16 @@ if {[get-define CXX] ne "false"} {
 }
 msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
 
+# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
+# but some compilers may not support it, so test here.
+switch -glob -- [get-define host] {
+       *-*-darwin* {
+               if {[cctest -cflags {-g0}]} {
+                       define cc-default-debug -g0
+               }
+       }
+}
+
 if {![cc-check-includes stdlib.h]} {
        user-error "Compiler does not work. See config.log"
 }
index 4c8f032..089ebcc 100755 (executable)
@@ -804,6 +804,9 @@ EOF
     *:MINGW*:*)
        echo ${UNAME_MACHINE}-pc-mingw32
        exit ;;
+    i*:MSYS*:*) 
+       echo ${UNAME_MACHINE}-pc-msys 
+       exit ;; 
     i*:windows32*:*)
        # uname -m includes "-pc" on this system.
        echo ${UNAME_MACHINE}-mingw32
index 320e303..a09498f 100755 (executable)
@@ -798,6 +798,10 @@ case $basic_machine in
                basic_machine=i370-ibm
                os=-mvs
                ;;
+       msys) 
+               basic_machine=i386-pc 
+               os=-msys 
+        ;; 
        ncr3000)
                basic_machine=i486-ncr
                os=-sysv4
@@ -1315,7 +1319,7 @@ case $os in
              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
              | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
              | -chorusos* | -chorusrdb* | -cegcc* \
-             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
              | -mingw32* | -linux-gnu* | -linux-android* \
              | -linux-newlib* | -linux-uclibc* \
              | -uxpv* | -beos* | -mpeix* | -udk* \
diff --git a/jim/autosetup/default.auto b/jim/autosetup/default.auto
new file mode 100755 (executable)
index 0000000..b36e0f8
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/
+# All rights reserved
+
+# Auto-load module for 'make' build system integration
+
+use init
+
+autosetup_add_init_type make {Simple "make" build system} {
+       autosetup_check_create auto.def \
+{# Initial auto.def created by 'autosetup --init=make'
+
+use cc
+
+# Add any user options here
+options {
+}
+
+make-config-header config.h
+make-template Makefile.in
+}
+
+       if {![file exists Makefile.in]} {
+               puts "Note: I don't see Makefile.in. You will probably need to create one."
+       }
+}
index 7ef152a..be7cf3d 100755 (executable)
@@ -3,12 +3,11 @@
 # If not found, builds a bootstrap jimsh from source
 d=`dirname "$0"`
 { "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0
-PATH="$PATH:$d"
+PATH="$PATH:$d"; export PATH
 for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do
        { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
 done
 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
-./make-bootstrap-jim > $d/jimsh0.c
 for cc in ${CC_FOR_BUILD:-cc} gcc; do
        { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
        "$d/jimsh0" "$d/test-tclsh" && exit 0
diff --git a/jim/autosetup/jimsh0.c b/jim/autosetup/jimsh0.c
new file mode 100644 (file)
index 0000000..c9380ac
--- /dev/null
@@ -0,0 +1,21604 @@
+/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */
+#define _GNU_SOURCE
+#define JIM_TCL_COMPAT
+#define JIM_REFERENCES
+#define JIM_ANSIC
+#define JIM_REGEXP
+#define HAVE_NO_AUTOCONF
+#define _JIMAUTOCONF_H
+#define TCL_LIBRARY "."
+#define jim_ext_bootstrap
+#define jim_ext_aio
+#define jim_ext_readdir
+#define jim_ext_glob
+#define jim_ext_regexp
+#define jim_ext_file
+#define jim_ext_exec
+#define jim_ext_clock
+#define jim_ext_array
+#define jim_ext_stdlib
+#define jim_ext_tclcompat
+#if defined(_MSC_VER)
+#define TCL_PLATFORM_OS "windows"
+#define TCL_PLATFORM_PLATFORM "windows"
+#define TCL_PLATFORM_PATH_SEPARATOR ";"
+#define HAVE_MKDIR_ONE_ARG
+#define HAVE_SYSTEM
+#elif defined(__MINGW32__)
+#define TCL_PLATFORM_OS "mingw"
+#define TCL_PLATFORM_PLATFORM "windows"
+#define TCL_PLATFORM_PATH_SEPARATOR ";"
+#define HAVE_MKDIR_ONE_ARG
+#define HAVE_SYSTEM
+#define HAVE_SYS_TIME_H
+#define HAVE_DIRENT_H
+#define HAVE_UNISTD_H
+#else
+#define TCL_PLATFORM_OS "unknown"
+#define TCL_PLATFORM_PLATFORM "unix"
+#define TCL_PLATFORM_PATH_SEPARATOR ":"
+#define HAVE_VFORK
+#define HAVE_WAITPID
+#define HAVE_ISATTY
+#define HAVE_SYS_TIME_H
+#define HAVE_DIRENT_H
+#define HAVE_UNISTD_H
+#endif
+#define JIM_VERSION 75
+#ifndef JIM_WIN32COMPAT_H
+#define JIM_WIN32COMPAT_H
+
+
+
+
+#if defined(_WIN32) || defined(WIN32)
+
+#define HAVE_DLOPEN
+void *dlopen(const char *path, int mode);
+int dlclose(void *handle);
+void *dlsym(void *handle, const char *symbol);
+char *dlerror(void);
+
+
+#define JIM_SPRINTF_DOUBLE_NEEDS_FIX
+
+#ifdef _MSC_VER
+
+
+#if _MSC_VER >= 1000
+       #pragma warning(disable:4146)
+#endif
+
+#include <limits.h>
+#define jim_wide _int64
+#ifndef LLONG_MAX
+       #define LLONG_MAX    9223372036854775807I64
+#endif
+#ifndef LLONG_MIN
+       #define LLONG_MIN    (-LLONG_MAX - 1I64)
+#endif
+#define JIM_WIDE_MIN LLONG_MIN
+#define JIM_WIDE_MAX LLONG_MAX
+#define JIM_WIDE_MODIFIER "I64d"
+#define strcasecmp _stricmp
+#define strtoull _strtoui64
+#define snprintf _snprintf
+
+#include <io.h>
+
+struct timeval {
+       long tv_sec;
+       long tv_usec;
+};
+
+int gettimeofday(struct timeval *tv, void *unused);
+
+#define HAVE_OPENDIR
+struct dirent {
+       char *d_name;
+};
+
+typedef struct DIR {
+       long                handle; 
+       struct _finddata_t  info;
+       struct dirent       result; 
+       char                *name;  
+} DIR;
+
+DIR *opendir(const char *name);
+int closedir(DIR *dir);
+struct dirent *readdir(DIR *dir);
+#endif 
+
+#endif 
+
+#endif
+#ifndef UTF8_UTIL_H
+#define UTF8_UTIL_H
+
+
+#define MAX_UTF8_LEN 4
+
+int utf8_fromunicode(char *p, unsigned uc);
+
+#ifndef JIM_UTF8
+#include <ctype.h>
+
+
+#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
+#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
+#define utf8_upper(C) toupper(C)
+#define utf8_title(C) toupper(C)
+#define utf8_lower(C) tolower(C)
+#define utf8_index(C, I) (I)
+#define utf8_charlen(C) 1
+#define utf8_prev_len(S, L) 1
+
+#else
+
+#endif
+
+#endif
+
+#ifndef __JIM__H
+#define __JIM__H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+#include <limits.h>
+#include <stdio.h>  
+#include <stdlib.h> 
+#include <stdarg.h> 
+
+
+#ifndef HAVE_NO_AUTOCONF
+#endif
+
+
+
+#ifndef jim_wide
+#  ifdef HAVE_LONG_LONG
+#    define jim_wide long long
+#    ifndef LLONG_MAX
+#      define LLONG_MAX    9223372036854775807LL
+#    endif
+#    ifndef LLONG_MIN
+#      define LLONG_MIN    (-LLONG_MAX - 1LL)
+#    endif
+#    define JIM_WIDE_MIN LLONG_MIN
+#    define JIM_WIDE_MAX LLONG_MAX
+#  else
+#    define jim_wide long
+#    define JIM_WIDE_MIN LONG_MIN
+#    define JIM_WIDE_MAX LONG_MAX
+#  endif
+
+
+#  ifdef HAVE_LONG_LONG
+#    define JIM_WIDE_MODIFIER "lld"
+#  else
+#    define JIM_WIDE_MODIFIER "ld"
+#    define strtoull strtoul
+#  endif
+#endif
+
+#define UCHAR(c) ((unsigned char)(c))
+
+
+#define JIM_OK 0
+#define JIM_ERR 1
+#define JIM_RETURN 2
+#define JIM_BREAK 3
+#define JIM_CONTINUE 4
+#define JIM_SIGNAL 5
+#define JIM_EXIT 6
+
+#define JIM_EVAL 7
+
+#define JIM_MAX_CALLFRAME_DEPTH 1000 
+#define JIM_MAX_EVAL_DEPTH 2000 
+
+#define JIM_NONE 0    
+#define JIM_ERRMSG 1    
+
+#define JIM_UNSHARED 4 
+#define JIM_MUSTEXIST 8    
+
+
+#define JIM_GLOBAL_ONLY 0x100
+
+
+#define JIM_SUBST_NOVAR 1 
+#define JIM_SUBST_NOCMD 2 
+#define JIM_SUBST_NOESC 4 
+#define JIM_SUBST_FLAG 128 
+
+
+#define JIM_NOTUSED(V) ((void) V)
+
+
+#define JIM_ENUM_ABBREV 2    
+
+
+#define JIM_CASESENS    0   
+#define JIM_NOCASE      1   
+
+
+#define JIM_PATH_LEN 1024
+
+
+#ifdef JIM_CRLF
+#define JIM_NL "\r\n"
+#else
+#define JIM_NL "\n"
+#endif
+
+#define JIM_LIBPATH "auto_path"
+#define JIM_INTERACTIVE "tcl_interactive"
+
+
+typedef struct Jim_Stack {
+    int len;
+    int maxlen;
+    void **vector;
+} Jim_Stack;
+
+
+typedef struct Jim_HashEntry {
+    void *key;
+    union {
+        void *val;
+        int intval;
+    } u;
+    struct Jim_HashEntry *next;
+} Jim_HashEntry;
+
+typedef struct Jim_HashTableType {
+    unsigned int (*hashFunction)(const void *key);
+    void *(*keyDup)(void *privdata, const void *key);
+    void *(*valDup)(void *privdata, const void *obj);
+    int (*keyCompare)(void *privdata, const void *key1, const void *key2);
+    void (*keyDestructor)(void *privdata, void *key);
+    void (*valDestructor)(void *privdata, void *obj);
+} Jim_HashTableType;
+
+typedef struct Jim_HashTable {
+    Jim_HashEntry **table;
+    const Jim_HashTableType *type;
+    unsigned int size;
+    unsigned int sizemask;
+    unsigned int used;
+    unsigned int collisions;
+    void *privdata;
+} Jim_HashTable;
+
+typedef struct Jim_HashTableIterator {
+    Jim_HashTable *ht;
+    int index;
+    Jim_HashEntry *entry, *nextEntry;
+} Jim_HashTableIterator;
+
+
+#define JIM_HT_INITIAL_SIZE     16
+
+
+#define Jim_FreeEntryVal(ht, entry) \
+    if ((ht)->type->valDestructor) \
+        (ht)->type->valDestructor((ht)->privdata, (entry)->u.val)
+
+#define Jim_SetHashVal(ht, entry, _val_) do { \
+    if ((ht)->type->valDup) \
+        entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
+    else \
+        entry->u.val = (_val_); \
+} while(0)
+
+#define Jim_FreeEntryKey(ht, entry) \
+    if ((ht)->type->keyDestructor) \
+        (ht)->type->keyDestructor((ht)->privdata, (entry)->key)
+
+#define Jim_SetHashKey(ht, entry, _key_) do { \
+    if ((ht)->type->keyDup) \
+        entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
+    else \
+        entry->key = (void *)(_key_); \
+} while(0)
+
+#define Jim_CompareHashKeys(ht, key1, key2) \
+    (((ht)->type->keyCompare) ? \
+        (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
+        (key1) == (key2))
+
+#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
+
+#define Jim_GetHashEntryKey(he) ((he)->key)
+#define Jim_GetHashEntryVal(he) ((he)->val)
+#define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
+#define Jim_GetHashTableSize(ht) ((ht)->size)
+#define Jim_GetHashTableUsed(ht) ((ht)->used)
+
+
+typedef struct Jim_Obj {
+    char *bytes; 
+    const struct Jim_ObjType *typePtr; 
+    int refCount; 
+    int length; 
+    
+    union {
+        
+        jim_wide wideValue;
+        
+        int intValue;
+        
+        double doubleValue;
+        
+        void *ptr;
+        
+        struct {
+            void *ptr1;
+            void *ptr2;
+        } twoPtrValue;
+        
+        struct {
+            unsigned long callFrameId; 
+            struct Jim_Var *varPtr;
+            int global; 
+        } varValue;
+        
+        struct {
+            unsigned long procEpoch; 
+            struct Jim_Obj *nsObj;
+            struct Jim_Cmd *cmdPtr;
+        } cmdValue;
+        
+        struct {
+            struct Jim_Obj **ele;    
+            int len;        
+            int maxLen;        
+        } listValue;
+        
+        struct {
+            int maxLength;
+            int charLength;     
+        } strValue;
+        
+        struct {
+            unsigned long id;
+            struct Jim_Reference *refPtr;
+        } refValue;
+        
+        struct {
+            struct Jim_Obj *fileNameObj;
+            int lineNumber;
+        } sourceValue;
+        
+        struct {
+            struct Jim_Obj *varNameObjPtr;
+            struct Jim_Obj *indexObjPtr;
+        } dictSubstValue;
+        
+        struct {
+            unsigned flags;
+            void *compre;       
+        } regexpValue;
+        struct {
+            int line;
+            int argc;
+        } scriptLineValue;
+    } internalRep;
+    struct Jim_Obj *prevObjPtr; 
+    struct Jim_Obj *nextObjPtr; 
+} Jim_Obj;
+
+
+#define Jim_IncrRefCount(objPtr) \
+    ++(objPtr)->refCount
+#define Jim_DecrRefCount(interp, objPtr) \
+    if (--(objPtr)->refCount <= 0) Jim_FreeObj(interp, objPtr)
+#define Jim_IsShared(objPtr) \
+    ((objPtr)->refCount > 1)
+
+#define Jim_FreeNewObj Jim_FreeObj
+
+
+#define Jim_FreeIntRep(i,o) \
+    if ((o)->typePtr && (o)->typePtr->freeIntRepProc) \
+        (o)->typePtr->freeIntRepProc(i, o)
+
+
+#define Jim_GetIntRepPtr(o) (o)->internalRep.ptr
+
+
+#define Jim_SetIntRepPtr(o, p) \
+    (o)->internalRep.ptr = (p)
+
+
+struct Jim_Interp;
+
+typedef void (Jim_FreeInternalRepProc)(struct Jim_Interp *interp,
+        struct Jim_Obj *objPtr);
+typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp,
+        struct Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr);
+
+typedef struct Jim_ObjType {
+    const char *name; 
+    Jim_FreeInternalRepProc *freeIntRepProc;
+    Jim_DupInternalRepProc *dupIntRepProc;
+    Jim_UpdateStringProc *updateStringProc;
+    int flags;
+} Jim_ObjType;
+
+
+#define JIM_TYPE_NONE 0        
+#define JIM_TYPE_REFERENCES 1    
+
+#define JIM_PRIV_FLAG_SHIFT 20
+
+
+
+typedef struct Jim_CallFrame {
+    unsigned long id; 
+    int level; 
+    struct Jim_HashTable vars; 
+    struct Jim_HashTable *staticVars; 
+    struct Jim_CallFrame *parent; 
+    Jim_Obj *const *argv; 
+    int argc; 
+    Jim_Obj *procArgsObjPtr; 
+    Jim_Obj *procBodyObjPtr; 
+    struct Jim_CallFrame *next; 
+    Jim_Obj *nsObj;             
+    Jim_Obj *fileNameObj;       
+    int line;
+    Jim_Stack *localCommands; 
+} Jim_CallFrame;
+
+typedef struct Jim_Var {
+    Jim_Obj *objPtr;
+    struct Jim_CallFrame *linkFramePtr;
+} Jim_Var;
+
+
+typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
+    Jim_Obj *const *argv);
+typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
+
+
+
+typedef struct Jim_Cmd {
+    int inUse;           
+    int isproc;          
+    struct Jim_Cmd *prevCmd;    
+    union {
+        struct {
+            
+            Jim_CmdProc cmdProc; 
+            Jim_DelCmdProc delProc; 
+            void *privData; 
+        } native;
+        struct {
+            
+            Jim_Obj *argListObjPtr;
+            Jim_Obj *bodyObjPtr;
+            Jim_HashTable *staticVars;  
+            int argListLen;             
+            int reqArity;               
+            int optArity;               
+            int argsPos;                
+            int upcall;                 
+            struct Jim_ProcArg {
+                Jim_Obj *nameObjPtr;    
+                Jim_Obj *defaultObjPtr; 
+            } *arglist;
+            Jim_Obj *nsObj;             
+        } proc;
+    } u;
+} Jim_Cmd;
+
+
+typedef struct Jim_PrngState {
+    unsigned char sbox[256];
+    unsigned int i, j;
+} Jim_PrngState;
+
+typedef struct Jim_Interp {
+    Jim_Obj *result; 
+    int errorLine; 
+    Jim_Obj *errorFileNameObj; 
+    int addStackTrace; 
+    int maxCallFrameDepth; 
+    int maxEvalDepth; 
+    int evalDepth;  
+    int returnCode; 
+    int returnLevel; 
+    int exitCode; 
+    long id; 
+    int signal_level; 
+    jim_wide sigmask;  
+    int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); 
+    Jim_CallFrame *framePtr; 
+    Jim_CallFrame *topFramePtr; 
+    struct Jim_HashTable commands; 
+    unsigned long procEpoch; /* Incremented every time the result
+                of procedures names lookup caching
+                may no longer be valid. */
+    unsigned long callFrameEpoch; /* Incremented every time a new
+                callframe is created. This id is used for the
+                'ID' field contained in the Jim_CallFrame
+                structure. */
+    int local; 
+    Jim_Obj *liveList; 
+    Jim_Obj *freeList; 
+    Jim_Obj *currentScriptObj; 
+    Jim_Obj *nullScriptObj; 
+    Jim_Obj *emptyObj; 
+    Jim_Obj *trueObj; 
+    Jim_Obj *falseObj; 
+    unsigned long referenceNextId; 
+    struct Jim_HashTable references; 
+    unsigned long lastCollectId; /* reference max Id of the last GC
+                execution. It's set to -1 while the collection
+                is running as sentinel to avoid to recursive
+                calls via the [collect] command inside
+                finalizers. */
+    time_t lastCollectTime; 
+    Jim_Obj *stackTrace; 
+    Jim_Obj *errorProc; 
+    Jim_Obj *unknown; 
+    int unknown_called; 
+    int errorFlag; 
+    void *cmdPrivData; /* Used to pass the private data pointer to
+                  a command. It is set to what the user specified
+                  via Jim_CreateCommand(). */
+
+    struct Jim_CallFrame *freeFramesList; 
+    struct Jim_HashTable assocData; 
+    Jim_PrngState *prngState; 
+    struct Jim_HashTable packages; 
+    Jim_Stack *loadHandles; 
+} Jim_Interp;
+
+#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++
+#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
+#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval))
+
+#define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b)
+#define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj)
+#define Jim_GetResult(i) ((i)->result)
+#define Jim_CmdPrivData(i) ((i)->cmdPrivData)
+
+#define Jim_SetResult(i,o) do {     \
+    Jim_Obj *_resultObjPtr_ = (o);    \
+    Jim_IncrRefCount(_resultObjPtr_); \
+    Jim_DecrRefCount(i,(i)->result);  \
+    (i)->result = _resultObjPtr_;     \
+} while(0)
+
+
+#define Jim_GetId(i) (++(i)->id)
+
+
+#define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference
+                                  string representation must be fixed length. */
+typedef struct Jim_Reference {
+    Jim_Obj *objPtr;
+    Jim_Obj *finalizerCmdNamePtr;
+    char tag[JIM_REFERENCE_TAGLEN+1];
+} Jim_Reference;
+
+
+
+#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
+
+
+
+#define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
+
+#define JIM_EXPORT
+
+
+JIM_EXPORT void *Jim_Alloc (int size);
+JIM_EXPORT void *Jim_Realloc(void *ptr, int size);
+JIM_EXPORT void Jim_Free (void *ptr);
+JIM_EXPORT char * Jim_StrDup (const char *s);
+JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
+
+
+JIM_EXPORT char **Jim_GetEnviron(void);
+JIM_EXPORT void Jim_SetEnviron(char **env);
+
+
+JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
+
+
+JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script);
+
+#define Jim_Eval_Named(I, S, F, L) Jim_EvalSource((I), (F), (L), (S))
+
+JIM_EXPORT int Jim_EvalGlobal(Jim_Interp *interp, const char *script);
+JIM_EXPORT int Jim_EvalFile(Jim_Interp *interp, const char *filename);
+JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename);
+JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr);
+JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc,
+        Jim_Obj *const *objv);
+JIM_EXPORT int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listObj);
+JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix,
+        int objc, Jim_Obj *const *objv);
+#define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov))
+JIM_EXPORT int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj);
+JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr,
+        Jim_Obj **resObjPtrPtr, int flags);
+
+
+JIM_EXPORT void Jim_InitStack(Jim_Stack *stack);
+JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack);
+JIM_EXPORT int Jim_StackLen(Jim_Stack *stack);
+JIM_EXPORT void Jim_StackPush(Jim_Stack *stack, void *element);
+JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack);
+JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack);
+JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr));
+
+
+JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht,
+        const Jim_HashTableType *type, void *privdata);
+JIM_EXPORT void Jim_ExpandHashTable (Jim_HashTable *ht,
+        unsigned int size);
+JIM_EXPORT int Jim_AddHashEntry (Jim_HashTable *ht, const void *key,
+        void *val);
+JIM_EXPORT int Jim_ReplaceHashEntry (Jim_HashTable *ht,
+        const void *key, void *val);
+JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht,
+        const void *key);
+JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht);
+JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht,
+        const void *key);
+JIM_EXPORT void Jim_ResizeHashTable (Jim_HashTable *ht);
+JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator
+        (Jim_HashTable *ht);
+JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry
+        (Jim_HashTableIterator *iter);
+
+
+JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
+JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
+JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
+JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
+        Jim_Obj *objPtr);
+JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
+        int *lenPtr);
+JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
+JIM_EXPORT int Jim_Length(Jim_Obj *objPtr);
+
+
+JIM_EXPORT Jim_Obj * Jim_NewStringObj (Jim_Interp *interp,
+        const char *s, int len);
+JIM_EXPORT Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp,
+        const char *s, int charlen);
+JIM_EXPORT Jim_Obj * Jim_NewStringObjNoAlloc (Jim_Interp *interp,
+        char *s, int len);
+JIM_EXPORT void Jim_AppendString (Jim_Interp *interp, Jim_Obj *objPtr,
+        const char *str, int len);
+JIM_EXPORT void Jim_AppendObj (Jim_Interp *interp, Jim_Obj *objPtr,
+        Jim_Obj *appendObjPtr);
+JIM_EXPORT void Jim_AppendStrings (Jim_Interp *interp,
+        Jim_Obj *objPtr, ...);
+JIM_EXPORT int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr);
+JIM_EXPORT int Jim_StringMatchObj (Jim_Interp *interp, Jim_Obj *patternObjPtr,
+        Jim_Obj *objPtr, int nocase);
+JIM_EXPORT Jim_Obj * Jim_StringRangeObj (Jim_Interp *interp,
+        Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr,
+        Jim_Obj *lastObjPtr);
+JIM_EXPORT Jim_Obj * Jim_FormatString (Jim_Interp *interp,
+        Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv);
+JIM_EXPORT Jim_Obj * Jim_ScanString (Jim_Interp *interp, Jim_Obj *strObjPtr,
+        Jim_Obj *fmtObjPtr, int flags);
+JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp,
+        Jim_Obj *objPtr, const char *str);
+JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr,
+        Jim_Obj *secondObjPtr, int nocase);
+JIM_EXPORT int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr,
+        Jim_Obj *secondObjPtr, int nocase);
+JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr);
+
+
+JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp,
+        Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr);
+JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp,
+        Jim_Obj *objPtr);
+JIM_EXPORT int Jim_SetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr);
+JIM_EXPORT int Jim_GetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr);
+
+
+JIM_EXPORT Jim_Interp * Jim_CreateInterp (void);
+JIM_EXPORT void Jim_FreeInterp (Jim_Interp *i);
+JIM_EXPORT int Jim_GetExitCode (Jim_Interp *interp);
+JIM_EXPORT const char *Jim_ReturnCode(int code);
+JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...);
+
+
+JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp);
+JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp,
+        const char *cmdName, Jim_CmdProc cmdProc, void *privData,
+         Jim_DelCmdProc delProc);
+JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp,
+        const char *cmdName);
+JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp,
+        const char *oldName, const char *newName);
+JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp,
+        Jim_Obj *objPtr, int flags);
+JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp,
+        Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr);
+JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp,
+        const char *name, Jim_Obj *objPtr);
+JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp,
+        const char *name, Jim_Obj *objPtr);
+JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
+        const char *name, const char *val);
+JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
+        Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
+        Jim_CallFrame *targetCallFrame);
+JIM_EXPORT int Jim_CreateNamespaceVariable(Jim_Interp *interp,
+        Jim_Obj *varNameObj, Jim_Obj *targetNameObj);
+JIM_EXPORT int Jim_DiscardNamespaceVars(Jim_Interp *interp);
+JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
+        Jim_Obj *nameObjPtr, int flags);
+JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
+        Jim_Obj *nameObjPtr, int flags);
+JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp,
+        const char *name, int flags);
+JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp,
+        const char *name, int flags);
+JIM_EXPORT int Jim_UnsetVariable (Jim_Interp *interp,
+        Jim_Obj *nameObjPtr, int flags);
+
+
+JIM_EXPORT Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp,
+        Jim_Obj *levelObjPtr);
+
+
+JIM_EXPORT int Jim_Collect (Jim_Interp *interp);
+JIM_EXPORT void Jim_CollectIfNeeded (Jim_Interp *interp);
+
+
+JIM_EXPORT int Jim_GetIndex (Jim_Interp *interp, Jim_Obj *objPtr,
+        int *indexPtr);
+
+
+JIM_EXPORT Jim_Obj * Jim_NewListObj (Jim_Interp *interp,
+        Jim_Obj *const *elements, int len);
+JIM_EXPORT void Jim_ListInsertElements (Jim_Interp *interp,
+        Jim_Obj *listPtr, int listindex, int objc, Jim_Obj *const *objVec);
+JIM_EXPORT void Jim_ListAppendElement (Jim_Interp *interp,
+        Jim_Obj *listPtr, Jim_Obj *objPtr);
+JIM_EXPORT void Jim_ListAppendList (Jim_Interp *interp,
+        Jim_Obj *listPtr, Jim_Obj *appendListPtr);
+JIM_EXPORT int Jim_ListLength (Jim_Interp *interp, Jim_Obj *objPtr);
+JIM_EXPORT int Jim_ListIndex (Jim_Interp *interp, Jim_Obj *listPrt,
+        int listindex, Jim_Obj **objPtrPtr, int seterr);
+JIM_EXPORT Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx);
+JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp,
+        Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc,
+        Jim_Obj *newObjPtr);
+JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc,
+        Jim_Obj *const *objv);
+JIM_EXPORT Jim_Obj *Jim_ListJoin(Jim_Interp *interp,
+        Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen);
+
+
+JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp,
+        Jim_Obj *const *elements, int len);
+JIM_EXPORT int Jim_DictKey (Jim_Interp *interp, Jim_Obj *dictPtr,
+        Jim_Obj *keyPtr, Jim_Obj **objPtrPtr, int flags);
+JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp,
+        Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc,
+        Jim_Obj **objPtrPtr, int flags);
+JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp,
+        Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc,
+        Jim_Obj *newObjPtr, int flags);
+JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
+        Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len);
+JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
+        Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
+JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
+JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
+JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
+
+
+JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
+        int *intPtr);
+
+
+JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp,
+        Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr);
+JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp,
+        Jim_Obj *exprObjPtr, int *boolPtr);
+
+
+JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr,
+        jim_wide *widePtr);
+JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr,
+        long *longPtr);
+#define Jim_NewWideObj  Jim_NewIntObj
+JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp,
+        jim_wide wideValue);
+
+
+JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
+        double *doublePtr);
+JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
+        double doubleValue);
+JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);
+
+
+JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
+        Jim_Obj *const *argv, const char *msg);
+JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
+        const char * const *tablePtr, int *indexPtr, const char *name, int flags);
+JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len,
+        char *stateCharPtr);
+JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
+
+
+typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data);
+JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key);
+JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key,
+        Jim_InterpDeleteProc *delProc, void *data);
+JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key);
+
+
+
+JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp,
+        const char *name, const char *ver, int flags);
+JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp,
+        const char *name, int flags);
+
+
+JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp);
+
+
+JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp);
+JIM_EXPORT void Jim_HistoryLoad(const char *filename);
+JIM_EXPORT void Jim_HistorySave(const char *filename);
+JIM_EXPORT char *Jim_HistoryGetline(const char *prompt);
+JIM_EXPORT void Jim_HistoryAdd(const char *line);
+JIM_EXPORT void Jim_HistoryShow(void);
+
+
+JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
+JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
+JIM_EXPORT int Jim_IsBigEndian(void);
+#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
+
+
+JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
+JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
+
+
+JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
+
+
+
+JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
+JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif 
+
+#ifndef JIM_SUBCMD_H
+#define JIM_SUBCMD_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define JIM_MODFLAG_HIDDEN   0x0001            
+#define JIM_MODFLAG_FULLARGV 0x0002            
+
+
+
+typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+
+typedef struct {
+       const char *cmd;                                
+       const char *args;                               
+       tclmod_cmd_function *function;  
+       short minargs;                                  
+       short maxargs;                                  
+       unsigned short flags;                   
+} jim_subcmd_type;
+
+const jim_subcmd_type *
+Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
+
+int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+
+int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+#ifndef JIMREGEXP_H
+#define JIMREGEXP_H
+
+#ifndef _JIMAUTOCONF_H
+#error Need jimautoconf.h
+#endif
+
+#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
+
+#include <regex.h>
+
+#else
+
+#include <stdlib.h>
+
+
+typedef struct {
+       int rm_so;
+       int rm_eo;
+} regmatch_t;
+
+
+typedef struct regexp {
+       
+       int re_nsub;            
+
+       
+       int cflags;                     
+       int err;                        
+       int regstart;           
+       int reganch;            
+       int regmust;            
+       int regmlen;            
+       int *program;           
+
+       
+       const char *regparse;           
+       int p;                          
+       int proglen;            
+
+       
+       int eflags;                             
+       const char *start;              
+       const char *reginput;   
+       const char *regbol;             
+
+       
+       regmatch_t *pmatch;             
+       int nmatch;                             
+} regexp;
+
+typedef regexp regex_t;
+
+#define REG_EXTENDED 0
+#define REG_NEWLINE 1
+#define REG_ICASE 2
+
+#define REG_NOTBOL 16
+
+enum {
+       REG_NOERROR,      
+       REG_NOMATCH,      
+       REG_BADPAT,               
+       REG_ERR_NULL_ARGUMENT,
+       REG_ERR_UNKNOWN,
+       REG_ERR_TOO_BIG,
+       REG_ERR_NOMEM,
+       REG_ERR_TOO_MANY_PAREN,
+       REG_ERR_UNMATCHED_PAREN,
+       REG_ERR_UNMATCHED_BRACES,
+       REG_ERR_BAD_COUNT,
+       REG_ERR_JUNK_ON_END,
+       REG_ERR_OPERAND_COULD_BE_EMPTY,
+       REG_ERR_NESTED_COUNT,
+       REG_ERR_INTERNAL,
+       REG_ERR_COUNT_FOLLOWS_NOTHING,
+       REG_ERR_TRAILING_BACKSLASH,
+       REG_ERR_CORRUPTED,
+       REG_ERR_NULL_CHAR,
+       REG_ERR_NUM
+};
+
+int regcomp(regex_t *preg, const char *regex, int cflags);
+int regexec(regex_t  *preg,  const  char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+size_t regerror(int errcode, const regex_t *preg, char *errbuf,  size_t errbuf_size);
+void regfree(regex_t *preg);
+
+#endif
+
+#endif
+int Jim_bootstrapInit(Jim_Interp *interp)
+{
+       if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG))
+               return JIM_ERR;
+
+       return Jim_EvalSource(interp, "bootstrap.tcl", 1,
+"\n"
+"\n"
+"proc package {args} {}\n"
+);
+}
+int Jim_initjimshInit(Jim_Interp *interp)
+{
+       if (Jim_PackageProvide(interp, "initjimsh", "1.0", JIM_ERRMSG))
+               return JIM_ERR;
+
+       return Jim_EvalSource(interp, "initjimsh.tcl", 1,
+"\n"
+"\n"
+"\n"
+"proc _jimsh_init {} {\n"
+"      rename _jimsh_init {}\n"
+"\n"
+"\n"
+"      lappend p {*}[split [env JIMLIB {}] $::tcl_platform(pathSeparator)]\n"
+"      lappend p {*}$::auto_path\n"
+"      lappend p [file dirname [info nameofexecutable]]\n"
+"      set ::auto_path $p\n"
+"\n"
+"      if {$::tcl_interactive && [env HOME {}] ne \"\"} {\n"
+"              foreach src {.jimrc jimrc.tcl} {\n"
+"                      if {[file exists [env HOME]/$src]} {\n"
+"                              uplevel #0 source [env HOME]/$src\n"
+"                              break\n"
+"                      }\n"
+"              }\n"
+"      }\n"
+"}\n"
+"\n"
+"if {$tcl_platform(platform) eq \"windows\"} {\n"
+"      set jim_argv0 [string map {\\\\ /} $jim_argv0]\n"
+"}\n"
+"\n"
+"_jimsh_init\n"
+);
+}
+int Jim_globInit(Jim_Interp *interp)
+{
+       if (Jim_PackageProvide(interp, "glob", "1.0", JIM_ERRMSG))
+               return JIM_ERR;
+
+       return Jim_EvalSource(interp, "glob.tcl", 1,
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"package require readdir\n"
+"\n"
+"\n"
+"proc glob.globdir {dir pattern} {\n"
+"      set result {}\n"
+"      set files [readdir $dir]\n"
+"      lappend files . ..\n"
+"\n"
+"      foreach name $files {\n"
+"              if {[string match $pattern $name]} {\n"
+"\n"
+"                      if {[string index $name 0] eq \".\" && [string index $pattern 0] ne \".\"} {\n"
+"                              continue\n"
+"                      }\n"
+"                      lappend result $name\n"
+"              }\n"
+"      }\n"
+"\n"
+"      return $result\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"proc glob.explode {pattern} {\n"
+"      set oldexp {}\n"
+"      set newexp {\"\"}\n"
+"\n"
+"      while 1 {\n"
+"              set oldexp $newexp\n"
+"              set newexp {}\n"
+"              set ob [string first \\{ $pattern]\n"
+"              set cb [string first \\} $pattern]\n"
+"\n"
+"              if {$ob < $cb && $ob != -1} {\n"
+"                      set mid [string range $pattern 0 $ob-1]\n"
+"                      set subexp [lassign [glob.explode [string range $pattern $ob+1 end]] pattern]\n"
+"                      if {$pattern eq \"\"} {\n"
+"                              error \"unmatched open brace in glob pattern\"\n"
+"                      }\n"
+"                      set pattern [string range $pattern 1 end]\n"
+"\n"
+"                      foreach subs $subexp {\n"
+"                              foreach sub [split $subs ,] {\n"
+"                                      foreach old $oldexp {\n"
+"                                              lappend newexp $old$mid$sub\n"
+"                                      }\n"
+"                              }\n"
+"                      }\n"
+"              } elseif {$cb != -1} {\n"
+"                      set suf  [string range $pattern 0 $cb-1]\n"
+"                      set rest [string range $pattern $cb end]\n"
+"                      break\n"
+"              } else {\n"
+"                      set suf  $pattern\n"
+"                      set rest \"\"\n"
+"                      break\n"
+"              }\n"
+"      }\n"
+"\n"
+"      foreach old $oldexp {\n"
+"              lappend newexp $old$suf\n"
+"      }\n"
+"      linsert $newexp 0 $rest\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"proc glob.glob {base pattern} {\n"
+"      set dir [file dirname $pattern]\n"
+"      if {$pattern eq $dir || $pattern eq \"\"} {\n"
+"              return [list [file join $base $dir] $pattern]\n"
+"      } elseif {$pattern eq [file tail $pattern]} {\n"
+"              set dir \"\"\n"
+"      }\n"
+"\n"
+"\n"
+"      set dirlist [glob.glob $base $dir]\n"
+"      set pattern [file tail $pattern]\n"
+"\n"
+"\n"
+"      set result {}\n"
+"      foreach {realdir dir} $dirlist {\n"
+"              if {![file isdir $realdir]} {\n"
+"                      continue\n"
+"              }\n"
+"              if {[string index $dir end] ne \"/\" && $dir ne \"\"} {\n"
+"                      append dir /\n"
+"              }\n"
+"              foreach name [glob.globdir $realdir $pattern] {\n"
+"                      lappend result [file join $realdir $name] $dir$name\n"
+"              }\n"
+"      }\n"
+"      return $result\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"proc glob {args} {\n"
+"      set nocomplain 0\n"
+"      set base \"\"\n"
+"\n"
+"      set n 0\n"
+"      foreach arg $args {\n"
+"              if {[info exists param]} {\n"
+"                      set $param $arg\n"
+"                      unset param\n"
+"                      incr n\n"
+"                      continue\n"
+"              }\n"
+"              switch -glob -- $arg {\n"
+"                      -d* {\n"
+"                              set switch $arg\n"
+"                              set param base\n"
+"                      }\n"
+"                      -n* {\n"
+"                              set nocomplain 1\n"
+"                      }\n"
+"                      -t* {\n"
+"\n"
+"                      }\n"
+"\n"
+"                      -* {\n"
+"                              return -code error \"bad option \\\"$switch\\\": must be -directory, -nocomplain, -tails, or --\"\n"
+"                      }\n"
+"                      -- {\n"
+"                              incr n\n"
+"                              break\n"
+"                      }\n"
+"                      *  {\n"
+"                              break\n"
+"                      }\n"
+"              }\n"
+"              incr n\n"
+"      }\n"
+"      if {[info exists param]} {\n"
+"              return -code error \"missing argument to \\\"$switch\\\"\"\n"
+"      }\n"
+"      if {[llength $args] <= $n} {\n"
+"              return -code error \"wrong # args: should be \\\"glob ?options? pattern ?pattern ...?\\\"\"\n"
+"      }\n"
+"\n"
+"      set args [lrange $args $n end]\n"
+"\n"
+"      set result {}\n"
+"      foreach pattern $args {\n"
+"              set pattern [string map {\n"
+"                      \\\\\\\\ \\x01 \\\\\\{ \\x02 \\\\\\} \\x03 \\\\, \\x04\n"
+"              } $pattern]\n"
+"              set patexps [lassign [glob.explode $pattern] rest]\n"
+"              if {$rest ne \"\"} {\n"
+"                      return -code error \"unmatched close brace in glob pattern\"\n"
+"              }\n"
+"              foreach patexp $patexps {\n"
+"                      set patexp [string map {\n"
+"                              \\x01 \\\\\\\\ \\x02 \\{ \\x03 \\} \\x04 ,\n"
+"                      } $patexp]\n"
+"                      foreach {realname name} [glob.glob $base $patexp] {\n"
+"                              lappend result $name\n"
+"                      }\n"
+"              }\n"
+"      }\n"
+"\n"
+"      if {!$nocomplain && [llength $result] == 0} {\n"
+"              return -code error \"no files matched glob patterns\"\n"
+"      }\n"
+"\n"
+"      return $result\n"
+"}\n"
+);
+}
+int Jim_stdlibInit(Jim_Interp *interp)
+{
+       if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG))
+               return JIM_ERR;
+
+       return Jim_EvalSource(interp, "stdlib.tcl", 1,
+"\n"
+"proc lambda {arglist args} {\n"
+"      tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n"
+"}\n"
+"\n"
+"proc lambda.finalizer {name val} {\n"
+"      rename $name {}\n"
+"}\n"
+"\n"
+"\n"
+"proc curry {args} {\n"
+"      alias [ref {} function lambda.finalizer] {*}$args\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"proc function {value} {\n"
+"      return $value\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"proc stacktrace {} {\n"
+"      set trace {}\n"
+"      foreach level [range 1 [info level]] {\n"
+"              lassign [info frame -$level] p f l\n"
+"              lappend trace $p $f $l\n"
+"      }\n"
+"      return $trace\n"
+"}\n"
+"\n"
+"\n"
+"proc stackdump {stacktrace} {\n"
+"      set result {}\n"
+"      set count 0\n"
+"      foreach {l f p} [lreverse $stacktrace] {\n"
+"              if {$count} {\n"
+"                      append result \\n\n"
+"              }\n"
+"              incr count\n"
+"              if {$p ne \"\"} {\n"
+"                      append result \"in procedure '$p' \"\n"
+"                      if {$f ne \"\"} {\n"
+"                              append result \"called \"\n"
+"                      }\n"
+"              }\n"
+"              if {$f ne \"\"} {\n"
+"                      append result \"at file \\\"$f\\\", line $l\"\n"
+"              }\n"
+"      }\n"
+"      return $result\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"proc errorInfo {msg {stacktrace \"\"}} {\n"
+"      if {$stacktrace eq \"\"} {\n"
+"              set stacktrace [info stacktrace]\n"
+"      }\n"
+"      lassign $stacktrace p f l\n"
+"      if {$f ne \"\"} {\n"
+"              set result \"Runtime Error: $f:$l: \"\n"
+"      }\n"
+"      append result \"$msg\\n\"\n"
+"      append result [stackdump $stacktrace]\n"
+"\n"
+"\n"
+"      string trim $result\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"proc {info nameofexecutable} {} {\n"
+"      if {[info exists ::jim_argv0]} {\n"
+"              if {[string match \"*/*\" $::jim_argv0]} {\n"
+"                      return [file join [pwd] $::jim_argv0]\n"
+"              }\n"
+"              foreach path [split [env PATH \"\"] $::tcl_platform(pathSeparator)] {\n"
+"                      set exec [file join [pwd] [string map {\\\\ /} $path] $::jim_argv0]\n"
+"                      if {[file executable $exec]} {\n"
+"                              return $exec\n"
+"                      }\n"
+"              }\n"
+"      }\n"
+"      return \"\"\n"
+"}\n"
+"\n"
+"\n"
+"proc {dict with} {dictVar args script} {\n"
+"      upvar $dictVar dict\n"
+"      set keys {}\n"
+"      foreach {n v} [dict get $dict {*}$args] {\n"
+"              upvar $n var_$n\n"
+"              set var_$n $v\n"
+"              lappend keys $n\n"
+"      }\n"
+"      catch {uplevel 1 $script} msg opts\n"
+"      if {[info exists dict] && [dict exists $dict {*}$args]} {\n"
+"              foreach n $keys {\n"
+"                      if {[info exists var_$n]} {\n"
+"                              dict set dict {*}$args $n [set var_$n]\n"
+"                      } else {\n"
+"                              dict unset dict {*}$args $n\n"
+"                      }\n"
+"              }\n"
+"      }\n"
+"      return {*}$opts $msg\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"proc {dict merge} {dict args} {\n"
+"      foreach d $args {\n"
+"\n"
+"              dict size $d\n"
+"              foreach {k v} $d {\n"
+"                      dict set dict $k $v\n"
+"              }\n"
+"      }\n"
+"      return $dict\n"
+"}\n"
+);
+}
+int Jim_tclcompatInit(Jim_Interp *interp)
+{
+       if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG))
+               return JIM_ERR;
+
+       return Jim_EvalSource(interp, "tclcompat.tcl", 1,
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"set env [env]\n"
+"\n"
+"if {[info commands stdout] ne \"\"} {\n"
+"\n"
+"      foreach p {gets flush close eof seek tell} {\n"
+"              proc $p {chan args} {p} {\n"
+"                      tailcall $chan $p {*}$args\n"
+"              }\n"
+"      }\n"
+"      unset p\n"
+"\n"
+"\n"
+"\n"
+"      proc puts {{-nonewline {}} {chan stdout} msg} {\n"
+"              if {${-nonewline} ni {-nonewline {}}} {\n"
+"                      tailcall ${-nonewline} puts $msg\n"
+"              }\n"
+"              tailcall $chan puts {*}${-nonewline} $msg\n"
+"      }\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"      proc read {{-nonewline {}} chan} {\n"
+"              if {${-nonewline} ni {-nonewline {}}} {\n"
+"                      tailcall ${-nonewline} read {*}${chan}\n"
+"              }\n"
+"              tailcall $chan read {*}${-nonewline}\n"
+"      }\n"
+"\n"
+"      proc fconfigure {f args} {\n"
+"              foreach {n v} $args {\n"
+"                      switch -glob -- $n {\n"
+"                              -bl* {\n"
+"                                      $f ndelay $(!$v)\n"
+"                              }\n"
+"                              -bu* {\n"
+"                                      $f buffering $v\n"
+"                              }\n"
+"                              -tr* {\n"
+"\n"
+"                              }\n"
+"                              default {\n"
+"                                      return -code error \"fconfigure: unknown option $n\"\n"
+"                              }\n"
+"                      }\n"
+"              }\n"
+"      }\n"
+"}\n"
+"\n"
+"\n"
+"proc case {var args} {\n"
+"\n"
+"      if {[lindex $args 0] eq \"in\"} {\n"
+"              set args [lrange $args 1 end]\n"
+"      }\n"
+"\n"
+"\n"
+"      if {[llength $args] == 1} {\n"
+"              set args [lindex $args 0]\n"
+"      }\n"
+"\n"
+"\n"
+"      if {[llength $args] % 2 != 0} {\n"
+"              return -code error \"extra case pattern with no body\"\n"
+"      }\n"
+"\n"
+"\n"
+"      local proc case.checker {value pattern} {\n"
+"              string match $pattern $value\n"
+"      }\n"
+"\n"
+"      foreach {value action} $args {\n"
+"              if {$value eq \"default\"} {\n"
+"                      set do_action $action\n"
+"                      continue\n"
+"              } elseif {[lsearch -bool -command case.checker $value $var]} {\n"
+"                      set do_action $action\n"
+"                      break\n"
+"              }\n"
+"      }\n"
+"\n"
+"      if {[info exists do_action]} {\n"
+"              set rc [catch [list uplevel 1 $do_action] result opts]\n"
+"              if {$rc} {\n"
+"                      incr opts(-level)\n"
+"              }\n"
+"              return {*}$opts $result\n"
+"      }\n"
+"}\n"
+"\n"
+"\n"
+"proc fileevent {args} {\n"
+"      tailcall {*}$args\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"proc parray {arrayname {pattern *} {puts puts}} {\n"
+"      upvar $arrayname a\n"
+"\n"
+"      set max 0\n"
+"      foreach name [array names a $pattern]] {\n"
+"              if {[string length $name] > $max} {\n"
+"                      set max [string length $name]\n"
+"              }\n"
+"      }\n"
+"      incr max [string length $arrayname]\n"
+"      incr max 2\n"
+"      foreach name [lsort [array names a $pattern]] {\n"
+"              $puts [format \"%-${max}s = %s\" $arrayname\\($name\\) $a($name)]\n"
+"      }\n"
+"}\n"
+"\n"
+"\n"
+"proc {file copy} {{force {}} source target} {\n"
+"      try {\n"
+"              if {$force ni {{} -force}} {\n"
+"                      error \"bad option \\\"$force\\\": should be -force\"\n"
+"              }\n"
+"\n"
+"              set in [open $source]\n"
+"\n"
+"              if {$force eq \"\" && [file exists $target]} {\n"
+"                      $in close\n"
+"                      error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n"
+"              }\n"
+"              set out [open $target w]\n"
+"              $in copyto $out\n"
+"              $out close\n"
+"      } on error {msg opts} {\n"
+"              incr opts(-level)\n"
+"              return {*}$opts $msg\n"
+"      } finally {\n"
+"              catch {$in close}\n"
+"      }\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"proc popen {cmd {mode r}} {\n"
+"      lassign [socket pipe] r w\n"
+"      try {\n"
+"              if {[string match \"w*\" $mode]} {\n"
+"                      lappend cmd <@$r &\n"
+"                      set pids [exec {*}$cmd]\n"
+"                      $r close\n"
+"                      set f $w\n"
+"              } else {\n"
+"                      lappend cmd >@$w &\n"
+"                      set pids [exec {*}$cmd]\n"
+"                      $w close\n"
+"                      set f $r\n"
+"              }\n"
+"              lambda {cmd args} {f pids} {\n"
+"                      if {$cmd eq \"pid\"} {\n"
+"                              return $pids\n"
+"                      }\n"
+"                      if {$cmd eq \"close\"} {\n"
+"                              $f close\n"
+"\n"
+"                              foreach p $pids { os.wait $p }\n"
+"                              return\n"
+"                      }\n"
+"                      tailcall $f $cmd {*}$args\n"
+"              }\n"
+"      } on error {error opts} {\n"
+"              $r close\n"
+"              $w close\n"
+"              error $error\n"
+"      }\n"
+"}\n"
+"\n"
+"\n"
+"local proc pid {{chan {}}} {\n"
+"      if {$chan eq \"\"} {\n"
+"              tailcall upcall pid\n"
+"      }\n"
+"      if {[catch {$chan tell}]} {\n"
+"              return -code error \"can not find channel named \\\"$chan\\\"\"\n"
+"      }\n"
+"      if {[catch {$chan pid} pids]} {\n"
+"              return \"\"\n"
+"      }\n"
+"      return $pids\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"proc try {args} {\n"
+"      set catchopts {}\n"
+"      while {[string match -* [lindex $args 0]]} {\n"
+"              set args [lassign $args opt]\n"
+"              if {$opt eq \"--\"} {\n"
+"                      break\n"
+"              }\n"
+"              lappend catchopts $opt\n"
+"      }\n"
+"      if {[llength $args] == 0} {\n"
+"              return -code error {wrong # args: should be \"try ?options? script ?argument ...?\"}\n"
+"      }\n"
+"      set args [lassign $args script]\n"
+"      set code [catch -eval {*}$catchopts [list uplevel 1 $script] msg opts]\n"
+"\n"
+"      set handled 0\n"
+"\n"
+"      foreach {on codes vars script} $args {\n"
+"              switch -- $on \\\n"
+"                      on {\n"
+"                              if {!$handled && ($codes eq \"*\" || [info returncode $code] in $codes)} {\n"
+"                                      lassign $vars msgvar optsvar\n"
+"                                      if {$msgvar ne \"\"} {\n"
+"                                              upvar $msgvar hmsg\n"
+"                                              set hmsg $msg\n"
+"                                      }\n"
+"                                      if {$optsvar ne \"\"} {\n"
+"                                              upvar $optsvar hopts\n"
+"                                              set hopts $opts\n"
+"                                      }\n"
+"\n"
+"                                      set code [catch [list uplevel 1 $script] msg opts]\n"
+"                                      incr handled\n"
+"                              }\n"
+"                      } \\\n"
+"                      finally {\n"
+"                              set finalcode [catch [list uplevel 1 $codes] finalmsg finalopts]\n"
+"                              if {$finalcode} {\n"
+"\n"
+"                                      set code $finalcode\n"
+"                                      set msg $finalmsg\n"
+"                                      set opts $finalopts\n"
+"                              }\n"
+"                              break\n"
+"                      } \\\n"
+"                      default {\n"
+"                              return -code error \"try: expected 'on' or 'finally', got '$on'\"\n"
+"                      }\n"
+"      }\n"
+"\n"
+"      if {$code} {\n"
+"              incr opts(-level)\n"
+"              return {*}$opts $msg\n"
+"      }\n"
+"      return $msg\n"
+"}\n"
+"\n"
+"\n"
+"\n"
+"proc throw {code {msg \"\"}} {\n"
+"      return -code $code $msg\n"
+"}\n"
+"\n"
+"\n"
+"proc {file delete force} {path} {\n"
+"      foreach e [readdir $path] {\n"
+"              file delete -force $path/$e\n"
+"      }\n"
+"      file delete $path\n"
+"}\n"
+);
+}
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+
+#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#else
+#define JIM_ANSIC
+#endif
+
+
+#define AIO_CMD_LEN 32      
+#define AIO_BUF_LEN 256     
+
+#ifndef HAVE_FTELLO
+    #define ftello ftell
+#endif
+#ifndef HAVE_FSEEKO
+    #define fseeko fseek
+#endif
+
+#define AIO_KEEPOPEN 1
+
+#if defined(JIM_IPV6)
+#define IPV6 1
+#else
+#define IPV6 0
+#ifndef PF_INET6
+#define PF_INET6 0
+#endif
+#endif
+
+
+typedef struct AioFile
+{
+    FILE *fp;
+    Jim_Obj *filename;
+    int type;
+    int OpenFlags;              
+    int fd;
+#ifdef O_NDELAY
+    int flags;
+#endif
+    Jim_Obj *rEvent;
+    Jim_Obj *wEvent;
+    Jim_Obj *eEvent;
+    int addr_family;
+} AioFile;
+
+static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
+    const char *hdlfmt, int family, const char *mode);
+
+
+static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name)
+{
+    if (name) {
+        Jim_SetResultFormatted(interp, "%#s: %s", name, strerror(errno));
+    }
+    else {
+        Jim_SetResultString(interp, strerror(errno), -1);
+    }
+}
+
+static void JimAioDelProc(Jim_Interp *interp, void *privData)
+{
+    AioFile *af = privData;
+
+    JIM_NOTUSED(interp);
+
+    if (!(af->OpenFlags & AIO_KEEPOPEN)) {
+        fclose(af->fp);
+    }
+
+    Jim_DecrRefCount(interp, af->filename);
+
+#ifdef jim_ext_eventloop
+    
+    Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
+#endif
+    Jim_Free(af);
+}
+
+static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
+{
+    if (!ferror(af->fp)) {
+        return JIM_OK;
+    }
+    clearerr(af->fp);
+    
+    if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
+        return JIM_OK;
+    }
+#ifdef ECONNRESET
+    if (errno == ECONNRESET) {
+        return JIM_OK;
+    }
+#endif
+#ifdef ECONNABORTED
+    if (errno != ECONNABORTED) {
+        return JIM_OK;
+    }
+#endif
+    JimAioSetError(interp, af->filename);
+    return JIM_ERR;
+}
+
+static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+    char buf[AIO_BUF_LEN];
+    Jim_Obj *objPtr;
+    int nonewline = 0;
+    jim_wide neededLen = -1;         
+
+    if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
+        nonewline = 1;
+        argv++;
+        argc--;
+    }
+    if (argc == 1) {
+        if (Jim_GetWide(interp, argv[0], &neededLen) != JIM_OK)
+            return JIM_ERR;
+        if (neededLen < 0) {
+            Jim_SetResultString(interp, "invalid parameter: negative len", -1);
+            return JIM_ERR;
+        }
+    }
+    else if (argc) {
+        return -1;
+    }
+    objPtr = Jim_NewStringObj(interp, NULL, 0);
+    while (neededLen != 0) {
+        int retval;
+        int readlen;
+
+        if (neededLen == -1) {
+            readlen = AIO_BUF_LEN;
+        }
+        else {
+            readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
+        }
+        retval = fread(buf, 1, readlen, af->fp);
+        if (retval > 0) {
+            Jim_AppendString(interp, objPtr, buf, retval);
+            if (neededLen != -1) {
+                neededLen -= retval;
+            }
+        }
+        if (retval != readlen)
+            break;
+    }
+    
+    if (JimCheckStreamError(interp, af)) {
+        Jim_FreeNewObj(interp, objPtr);
+        return JIM_ERR;
+    }
+    if (nonewline) {
+        int len;
+        const char *s = Jim_GetString(objPtr, &len);
+
+        if (len > 0 && s[len - 1] == '\n') {
+            objPtr->length--;
+            objPtr->bytes[objPtr->length] = '\0';
+        }
+    }
+    Jim_SetResult(interp, objPtr);
+    return JIM_OK;
+}
+
+static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+    jim_wide count = 0;
+    jim_wide maxlen = JIM_WIDE_MAX;
+    FILE *outfh = Jim_AioFilehandle(interp, argv[0]);
+
+    if (outfh == NULL) {
+        return JIM_ERR;
+    }
+
+    if (argc == 2) {
+        if (Jim_GetWide(interp, argv[1], &maxlen) != JIM_OK) {
+            return JIM_ERR;
+        }
+    }
+
+    while (count < maxlen) {
+        int ch = fgetc(af->fp);
+
+        if (ch == EOF || fputc(ch, outfh) == EOF) {
+            break;
+        }
+        count++;
+    }
+
+    if (ferror(af->fp)) {
+        Jim_SetResultFormatted(interp, "error while reading: %s", strerror(errno));
+        clearerr(af->fp);
+        return JIM_ERR;
+    }
+
+    if (ferror(outfh)) {
+        Jim_SetResultFormatted(interp, "error while writing: %s", strerror(errno));
+        clearerr(outfh);
+        return JIM_ERR;
+    }
+
+    Jim_SetResultInt(interp, count);
+
+    return JIM_OK;
+}
+
+static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+    char buf[AIO_BUF_LEN];
+    Jim_Obj *objPtr;
+    int len;
+
+    errno = 0;
+
+    objPtr = Jim_NewStringObj(interp, NULL, 0);
+    while (1) {
+        buf[AIO_BUF_LEN - 1] = '_';
+        if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL)
+            break;
+
+        if (buf[AIO_BUF_LEN - 1] == '\0' && buf[AIO_BUF_LEN - 2] != '\n') {
+            Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN - 1);
+        }
+        else {
+            len = strlen(buf);
+
+            if (len && (buf[len - 1] == '\n')) {
+                
+                len--;
+            }
+
+            Jim_AppendString(interp, objPtr, buf, len);
+            break;
+        }
+    }
+    if (JimCheckStreamError(interp, af)) {
+        
+        Jim_FreeNewObj(interp, objPtr);
+        return JIM_ERR;
+    }
+
+    if (argc) {
+        if (Jim_SetVariable(interp, argv[0], objPtr) != JIM_OK) {
+            Jim_FreeNewObj(interp, objPtr);
+            return JIM_ERR;
+        }
+
+        len = Jim_Length(objPtr);
+
+        if (len == 0 && feof(af->fp)) {
+            
+            len = -1;
+        }
+        Jim_SetResultInt(interp, len);
+    }
+    else {
+        Jim_SetResult(interp, objPtr);
+    }
+    return JIM_OK;
+}
+
+static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+    int wlen;
+    const char *wdata;
+    Jim_Obj *strObj;
+
+    if (argc == 2) {
+        if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
+            return -1;
+        }
+        strObj = argv[1];
+    }
+    else {
+        strObj = argv[0];
+    }
+
+    wdata = Jim_GetString(strObj, &wlen);
+    if (fwrite(wdata, 1, wlen, af->fp) == (unsigned)wlen) {
+        if (argc == 2 || putc('\n', af->fp) != EOF) {
+            return JIM_OK;
+        }
+    }
+    JimAioSetError(interp, af->filename);
+    return JIM_ERR;
+}
+
+static int aio_cmd_isatty(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+#ifdef HAVE_ISATTY
+    AioFile *af = Jim_CmdPrivData(interp);
+    Jim_SetResultInt(interp, isatty(fileno(af->fp)));
+#else
+    Jim_SetResultInt(interp, 0);
+#endif
+
+    return JIM_OK;
+}
+
+
+static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    if (fflush(af->fp) == EOF) {
+        JimAioSetError(interp, af->filename);
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    Jim_SetResultInt(interp, feof(af->fp));
+    return JIM_OK;
+}
+
+static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_DeleteCommand(interp, Jim_String(argv[0]));
+    return JIM_OK;
+}
+
+static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+    int orig = SEEK_SET;
+    jim_wide offset;
+
+    if (argc == 2) {
+        if (Jim_CompareStringImmediate(interp, argv[1], "start"))
+            orig = SEEK_SET;
+        else if (Jim_CompareStringImmediate(interp, argv[1], "current"))
+            orig = SEEK_CUR;
+        else if (Jim_CompareStringImmediate(interp, argv[1], "end"))
+            orig = SEEK_END;
+        else {
+            return -1;
+        }
+    }
+    if (Jim_GetWide(interp, argv[0], &offset) != JIM_OK) {
+        return JIM_ERR;
+    }
+    if (fseeko(af->fp, offset, orig) == -1) {
+        JimAioSetError(interp, af->filename);
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    Jim_SetResultInt(interp, ftello(af->fp));
+    return JIM_OK;
+}
+
+static int aio_cmd_filename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    Jim_SetResult(interp, af->filename);
+    return JIM_OK;
+}
+
+#ifdef O_NDELAY
+static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    int fmode = af->flags;
+
+    if (argc) {
+        long nb;
+
+        if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) {
+            return JIM_ERR;
+        }
+        if (nb) {
+            fmode |= O_NDELAY;
+        }
+        else {
+            fmode &= ~O_NDELAY;
+        }
+        fcntl(af->fd, F_SETFL, fmode);
+        af->flags = fmode;
+    }
+    Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
+    return JIM_OK;
+}
+#endif
+
+static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    static const char * const options[] = {
+        "none",
+        "line",
+        "full",
+        NULL
+    };
+    enum
+    {
+        OPT_NONE,
+        OPT_LINE,
+        OPT_FULL,
+    };
+    int option;
+
+    if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
+        return JIM_ERR;
+    }
+    switch (option) {
+        case OPT_NONE:
+            setvbuf(af->fp, NULL, _IONBF, 0);
+            break;
+        case OPT_LINE:
+            setvbuf(af->fp, NULL, _IOLBF, BUFSIZ);
+            break;
+        case OPT_FULL:
+            setvbuf(af->fp, NULL, _IOFBF, BUFSIZ);
+            break;
+    }
+    return JIM_OK;
+}
+
+#ifdef jim_ext_eventloop
+static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
+{
+    Jim_Obj **objPtrPtr = clientData;
+
+    Jim_DecrRefCount(interp, *objPtrPtr);
+    *objPtrPtr = NULL;
+}
+
+static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
+{
+    Jim_Obj **objPtrPtr = clientData;
+
+    return Jim_EvalObjBackground(interp, *objPtrPtr);
+}
+
+static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
+    int argc, Jim_Obj * const *argv)
+{
+    if (argc == 0) {
+        
+        if (*scriptHandlerObj) {
+            Jim_SetResult(interp, *scriptHandlerObj);
+        }
+        return JIM_OK;
+    }
+
+    if (*scriptHandlerObj) {
+        
+        Jim_DeleteFileHandler(interp, af->fp, mask);
+    }
+
+    
+    if (Jim_Length(argv[0]) == 0) {
+        
+        return JIM_OK;
+    }
+
+    
+    Jim_IncrRefCount(argv[0]);
+    *scriptHandlerObj = argv[0];
+
+    Jim_CreateFileHandler(interp, af->fp, mask,
+        JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
+
+    return JIM_OK;
+}
+
+static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    return aio_eventinfo(interp, af, JIM_EVENT_READABLE, &af->rEvent, argc, argv);
+}
+
+static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv);
+}
+
+static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    AioFile *af = Jim_CmdPrivData(interp);
+
+    return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
+}
+#endif
+
+static const jim_subcmd_type aio_command_table[] = {
+    {   "read",
+        "?-nonewline? ?len?",
+        aio_cmd_read,
+        0,
+        2,
+        
+    },
+    {   "copyto",
+        "handle ?size?",
+        aio_cmd_copy,
+        1,
+        2,
+        
+    },
+    {   "gets",
+        "?var?",
+        aio_cmd_gets,
+        0,
+        1,
+        
+    },
+    {   "puts",
+        "?-nonewline? str",
+        aio_cmd_puts,
+        1,
+        2,
+        
+    },
+    {   "isatty",
+        NULL,
+        aio_cmd_isatty,
+        0,
+        0,
+        
+    },
+    {   "flush",
+        NULL,
+        aio_cmd_flush,
+        0,
+        0,
+        
+    },
+    {   "eof",
+        NULL,
+        aio_cmd_eof,
+        0,
+        0,
+        
+    },
+    {   "close",
+        NULL,
+        aio_cmd_close,
+        0,
+        0,
+        JIM_MODFLAG_FULLARGV,
+        
+    },
+    {   "seek",
+        "offset ?start|current|end",
+        aio_cmd_seek,
+        1,
+        2,
+        
+    },
+    {   "tell",
+        NULL,
+        aio_cmd_tell,
+        0,
+        0,
+        
+    },
+    {   "filename",
+        NULL,
+        aio_cmd_filename,
+        0,
+        0,
+        
+    },
+#ifdef O_NDELAY
+    {   "ndelay",
+        "?0|1?",
+        aio_cmd_ndelay,
+        0,
+        1,
+        
+    },
+#endif
+    {   "buffering",
+        "none|line|full",
+        aio_cmd_buffering,
+        1,
+        1,
+        
+    },
+#ifdef jim_ext_eventloop
+    {   "readable",
+        "?readable-script?",
+        aio_cmd_readable,
+        0,
+        1,
+        
+    },
+    {   "writable",
+        "?writable-script?",
+        aio_cmd_writable,
+        0,
+        1,
+        
+    },
+    {   "onexception",
+        "?exception-script?",
+        aio_cmd_onexception,
+        0,
+        1,
+        
+    },
+#endif
+    { NULL }
+};
+
+static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv);
+}
+
+static int JimAioOpenCommand(Jim_Interp *interp, int argc,
+        Jim_Obj *const *argv)
+{
+    const char *mode;
+    const char *filename;
+
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
+        return JIM_ERR;
+    }
+
+    mode = (argc == 3) ? Jim_String(argv[2]) : "r";
+    filename = Jim_String(argv[1]);
+
+#ifdef jim_ext_tclcompat
+    
+    if (*filename == '|') {
+        Jim_Obj *evalObj[3];
+
+        evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
+        evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
+        evalObj[2] = Jim_NewStringObj(interp, mode, -1);
+
+        return Jim_EvalObjVector(interp, 3, evalObj);
+    }
+#endif
+    return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
+}
+
+static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
+    const char *hdlfmt, int family, const char *mode)
+{
+    AioFile *af;
+    char buf[AIO_CMD_LEN];
+    int OpenFlags = 0;
+
+    if (filename == NULL) {
+        filename = Jim_NewStringObj(interp, hdlfmt, -1);
+    }
+
+    Jim_IncrRefCount(filename);
+
+    if (fh == NULL) {
+        if (fd < 0) {
+            fh = fopen(Jim_String(filename), mode);
+        }
+        else {
+            fh = fdopen(fd, mode);
+        }
+    }
+    else {
+        OpenFlags = AIO_KEEPOPEN;
+    }
+
+    if (fh == NULL) {
+        JimAioSetError(interp, filename);
+#if !defined(JIM_ANSIC)
+        if (fd >= 0) {
+            close(fd);
+        }
+#endif
+        Jim_DecrRefCount(interp, filename);
+        return JIM_ERR;
+    }
+
+    
+    af = Jim_Alloc(sizeof(*af));
+    memset(af, 0, sizeof(*af));
+    af->fp = fh;
+    af->fd = fileno(fh);
+    af->filename = filename;
+#ifdef FD_CLOEXEC
+    if ((OpenFlags & AIO_KEEPOPEN) == 0) {
+        fcntl(af->fd, F_SETFD, FD_CLOEXEC);
+    }
+#endif
+    af->OpenFlags = OpenFlags;
+#ifdef O_NDELAY
+    af->flags = fcntl(af->fd, F_GETFL);
+#endif
+    af->addr_family = family;
+    snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
+    Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
+
+    Jim_SetResultString(interp, buf, -1);
+
+    return JIM_OK;
+}
+
+
+FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
+{
+    Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
+
+    if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
+        return ((AioFile *) cmdPtr->u.native.privData)->fp;
+    }
+    Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
+    return NULL;
+}
+
+int Jim_aioInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
+#ifndef JIM_ANSIC
+    Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
+#endif
+
+    
+    JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
+    JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
+    JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
+
+    return JIM_OK;
+}
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
+int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *dirPath;
+    DIR *dirPtr;
+    struct dirent *entryPtr;
+    int nocomplain = 0;
+
+    if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) {
+        nocomplain = 1;
+    }
+    if (argc != 2 && !nocomplain) {
+        Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath");
+        return JIM_ERR;
+    }
+
+    dirPath = Jim_String(argv[1 + nocomplain]);
+
+    dirPtr = opendir(dirPath);
+    if (dirPtr == NULL) {
+        if (nocomplain) {
+            return JIM_OK;
+        }
+        Jim_SetResultString(interp, strerror(errno), -1);
+        return JIM_ERR;
+    }
+    Jim_SetResultString(interp, strerror(errno), -1);
+
+    Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+
+    while ((entryPtr = readdir(dirPtr)) != NULL) {
+        if (entryPtr->d_name[0] == '.') {
+            if (entryPtr->d_name[1] == '\0') {
+                continue;
+            }
+            if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
+                continue;
+        }
+        Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
+                entryPtr->d_name, -1));
+    }
+    closedir(dirPtr);
+
+    return JIM_OK;
+}
+
+int Jim_readdirInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
+    return JIM_OK;
+}
+
+#include <stdlib.h>
+#include <string.h>
+
+
+static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    regfree(objPtr->internalRep.regexpValue.compre);
+    Jim_Free(objPtr->internalRep.regexpValue.compre);
+}
+
+static const Jim_ObjType regexpObjType = {
+    "regexp",
+    FreeRegexpInternalRep,
+    NULL,
+    NULL,
+    JIM_TYPE_NONE
+};
+
+static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned flags)
+{
+    regex_t *compre;
+    const char *pattern;
+    int ret;
+
+    
+    if (objPtr->typePtr == &regexpObjType &&
+        objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) {
+        
+        return objPtr->internalRep.regexpValue.compre;
+    }
+
+    
+
+    
+    pattern = Jim_String(objPtr);
+    compre = Jim_Alloc(sizeof(regex_t));
+
+    if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) {
+        char buf[100];
+
+        regerror(ret, compre, buf, sizeof(buf));
+        Jim_SetResultFormatted(interp, "couldn't compile regular expression pattern: %s", buf);
+        regfree(compre);
+        Jim_Free(compre);
+        return NULL;
+    }
+
+    Jim_FreeIntRep(interp, objPtr);
+
+    objPtr->typePtr = &regexpObjType;
+    objPtr->internalRep.regexpValue.flags = flags;
+    objPtr->internalRep.regexpValue.compre = compre;
+
+    return compre;
+}
+
+int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int opt_indices = 0;
+    int opt_all = 0;
+    int opt_inline = 0;
+    regex_t *regex;
+    int match, i, j;
+    int offset = 0;
+    regmatch_t *pmatch = NULL;
+    int source_len;
+    int result = JIM_OK;
+    const char *pattern;
+    const char *source_str;
+    int num_matches = 0;
+    int num_vars;
+    Jim_Obj *resultListObj = NULL;
+    int regcomp_flags = 0;
+    int eflags = 0;
+    int option;
+    enum {
+        OPT_INDICES,  OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_INLINE, OPT_START, OPT_END
+    };
+    static const char * const options[] = {
+        "-indices", "-nocase", "-line", "-all", "-inline", "-start", "--", NULL
+    };
+
+    if (argc < 3) {
+      wrongNumArgs:
+        Jim_WrongNumArgs(interp, 1, argv,
+            "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
+        return JIM_ERR;
+    }
+
+    for (i = 1; i < argc; i++) {
+        const char *opt = Jim_String(argv[i]);
+
+        if (*opt != '-') {
+            break;
+        }
+        if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+            return JIM_ERR;
+        }
+        if (option == OPT_END) {
+            i++;
+            break;
+        }
+        switch (option) {
+            case OPT_INDICES:
+                opt_indices = 1;
+                break;
+
+            case OPT_NOCASE:
+                regcomp_flags |= REG_ICASE;
+                break;
+
+            case OPT_LINE:
+                regcomp_flags |= REG_NEWLINE;
+                break;
+
+            case OPT_ALL:
+                opt_all = 1;
+                break;
+
+            case OPT_INLINE:
+                opt_inline = 1;
+                break;
+
+            case OPT_START:
+                if (++i == argc) {
+                    goto wrongNumArgs;
+                }
+                if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) {
+                    return JIM_ERR;
+                }
+                break;
+        }
+    }
+    if (argc - i < 2) {
+        goto wrongNumArgs;
+    }
+
+    regex = SetRegexpFromAny(interp, argv[i], regcomp_flags);
+    if (!regex) {
+        return JIM_ERR;
+    }
+
+    pattern = Jim_String(argv[i]);
+    source_str = Jim_GetString(argv[i + 1], &source_len);
+
+    num_vars = argc - i - 2;
+
+    if (opt_inline) {
+        if (num_vars) {
+            Jim_SetResultString(interp, "regexp match variables not allowed when using -inline",
+                -1);
+            result = JIM_ERR;
+            goto done;
+        }
+        num_vars = regex->re_nsub + 1;
+    }
+
+    pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch));
+
+    if (offset) {
+        if (offset < 0) {
+            offset += source_len + 1;
+        }
+        if (offset > source_len) {
+            source_str += source_len;
+        }
+        else if (offset > 0) {
+            source_str += offset;
+        }
+        eflags |= REG_NOTBOL;
+    }
+
+    if (opt_inline) {
+        resultListObj = Jim_NewListObj(interp, NULL, 0);
+    }
+
+  next_match:
+    match = regexec(regex, source_str, num_vars + 1, pmatch, eflags);
+    if (match >= REG_BADPAT) {
+        char buf[100];
+
+        regerror(match, regex, buf, sizeof(buf));
+        Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf);
+        result = JIM_ERR;
+        goto done;
+    }
+
+    if (match == REG_NOMATCH) {
+        goto done;
+    }
+
+    num_matches++;
+
+    if (opt_all && !opt_inline) {
+        
+        goto try_next_match;
+    }
+
+
+    j = 0;
+    for (i += 2; opt_inline ? j < num_vars : i < argc; i++, j++) {
+        Jim_Obj *resultObj;
+
+        if (opt_indices) {
+            resultObj = Jim_NewListObj(interp, NULL, 0);
+        }
+        else {
+            resultObj = Jim_NewStringObj(interp, "", 0);
+        }
+
+        if (pmatch[j].rm_so == -1) {
+            if (opt_indices) {
+                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
+                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
+            }
+        }
+        else {
+            int len = pmatch[j].rm_eo - pmatch[j].rm_so;
+
+            if (opt_indices) {
+                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp,
+                        offset + pmatch[j].rm_so));
+                Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp,
+                        offset + pmatch[j].rm_so + len - 1));
+            }
+            else {
+                Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len);
+            }
+        }
+
+        if (opt_inline) {
+            Jim_ListAppendElement(interp, resultListObj, resultObj);
+        }
+        else {
+            
+            result = Jim_SetVariable(interp, argv[i], resultObj);
+
+            if (result != JIM_OK) {
+                Jim_FreeObj(interp, resultObj);
+                break;
+            }
+        }
+    }
+
+  try_next_match:
+    if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) {
+        if (pmatch[0].rm_eo) {
+            offset += pmatch[0].rm_eo;
+            source_str += pmatch[0].rm_eo;
+        }
+        else {
+            source_str++;
+            offset++;
+        }
+        if (*source_str) {
+            eflags = REG_NOTBOL;
+            goto next_match;
+        }
+    }
+
+  done:
+    if (result == JIM_OK) {
+        if (opt_inline) {
+            Jim_SetResult(interp, resultListObj);
+        }
+        else {
+            Jim_SetResultInt(interp, num_matches);
+        }
+    }
+
+    Jim_Free(pmatch);
+    return result;
+}
+
+#define MAX_SUB_MATCHES 50
+
+int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int regcomp_flags = 0;
+    int regexec_flags = 0;
+    int opt_all = 0;
+    int offset = 0;
+    regex_t *regex;
+    const char *p;
+    int result;
+    regmatch_t pmatch[MAX_SUB_MATCHES + 1];
+    int num_matches = 0;
+
+    int i, j, n;
+    Jim_Obj *varname;
+    Jim_Obj *resultObj;
+    const char *source_str;
+    int source_len;
+    const char *replace_str;
+    int replace_len;
+    const char *pattern;
+    int option;
+    enum {
+        OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_END
+    };
+    static const char * const options[] = {
+        "-nocase", "-line", "-all", "-start", "--", NULL
+    };
+
+    if (argc < 4) {
+      wrongNumArgs:
+        Jim_WrongNumArgs(interp, 1, argv,
+            "?switches? exp string subSpec ?varName?");
+        return JIM_ERR;
+    }
+
+    for (i = 1; i < argc; i++) {
+        const char *opt = Jim_String(argv[i]);
+
+        if (*opt != '-') {
+            break;
+        }
+        if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+            return JIM_ERR;
+        }
+        if (option == OPT_END) {
+            i++;
+            break;
+        }
+        switch (option) {
+            case OPT_NOCASE:
+                regcomp_flags |= REG_ICASE;
+                break;
+
+            case OPT_LINE:
+                regcomp_flags |= REG_NEWLINE;
+                break;
+
+            case OPT_ALL:
+                opt_all = 1;
+                break;
+
+            case OPT_START:
+                if (++i == argc) {
+                    goto wrongNumArgs;
+                }
+                if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) {
+                    return JIM_ERR;
+                }
+                break;
+        }
+    }
+    if (argc - i != 3 && argc - i != 4) {
+        goto wrongNumArgs;
+    }
+
+    regex = SetRegexpFromAny(interp, argv[i], regcomp_flags);
+    if (!regex) {
+        return JIM_ERR;
+    }
+    pattern = Jim_String(argv[i]);
+
+    source_str = Jim_GetString(argv[i + 1], &source_len);
+    replace_str = Jim_GetString(argv[i + 2], &replace_len);
+    varname = argv[i + 3];
+
+    
+    resultObj = Jim_NewStringObj(interp, "", 0);
+
+    if (offset) {
+        if (offset < 0) {
+            offset += source_len + 1;
+        }
+        if (offset > source_len) {
+            offset = source_len;
+        }
+        else if (offset < 0) {
+            offset = 0;
+        }
+    }
+
+    
+    Jim_AppendString(interp, resultObj, source_str, offset);
+
+
+    n = source_len - offset;
+    p = source_str + offset;
+    do {
+        int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags);
+
+        if (match >= REG_BADPAT) {
+            char buf[100];
+
+            regerror(match, regex, buf, sizeof(buf));
+            Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf);
+            return JIM_ERR;
+        }
+        if (match == REG_NOMATCH) {
+            break;
+        }
+
+        num_matches++;
+
+        Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so);
+
+
+        for (j = 0; j < replace_len; j++) {
+            int idx;
+            int c = replace_str[j];
+
+            if (c == '&') {
+                idx = 0;
+            }
+            else if (c == '\\' && j < replace_len) {
+                c = replace_str[++j];
+                if ((c >= '0') && (c <= '9')) {
+                    idx = c - '0';
+                }
+                else if ((c == '\\') || (c == '&')) {
+                    Jim_AppendString(interp, resultObj, replace_str + j, 1);
+                    continue;
+                }
+                else {
+                    Jim_AppendString(interp, resultObj, replace_str + j - 1, 2);
+                    continue;
+                }
+            }
+            else {
+                Jim_AppendString(interp, resultObj, replace_str + j, 1);
+                continue;
+            }
+            if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) {
+                Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so,
+                    pmatch[idx].rm_eo - pmatch[idx].rm_so);
+            }
+        }
+
+        p += pmatch[0].rm_eo;
+        n -= pmatch[0].rm_eo;
+
+        
+        if (!opt_all || n == 0) {
+            break;
+        }
+
+        
+        if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
+            break;
+        }
+
+        
+        if (pattern[0] == '\0' && n) {
+            
+            Jim_AppendString(interp, resultObj, p, 1);
+            p++;
+            n--;
+        }
+
+        regexec_flags |= REG_NOTBOL;
+    } while (n);
+
+    Jim_AppendString(interp, resultObj, p, -1);
+
+    
+    if (argc - i == 4) {
+        result = Jim_SetVariable(interp, varname, resultObj);
+
+        if (result == JIM_OK) {
+            Jim_SetResultInt(interp, num_matches);
+        }
+        else {
+            Jim_FreeObj(interp, resultObj);
+        }
+    }
+    else {
+        Jim_SetResult(interp, resultObj);
+        result = JIM_OK;
+    }
+
+    return result;
+}
+
+int Jim_regexpInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL);
+    Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL);
+    return JIM_OK;
+}
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+
+#ifdef HAVE_UTIMES
+#include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined(_MSC_VER)
+#include <direct.h>
+#define F_OK 0
+#define W_OK 2
+#define R_OK 4
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+# ifndef MAXPATHLEN
+# define MAXPATHLEN JIM_PATH_LEN
+# endif
+
+
+static const char *JimGetFileType(int mode)
+{
+    if (S_ISREG(mode)) {
+        return "file";
+    }
+    else if (S_ISDIR(mode)) {
+        return "directory";
+    }
+#ifdef S_ISCHR
+    else if (S_ISCHR(mode)) {
+        return "characterSpecial";
+    }
+#endif
+#ifdef S_ISBLK
+    else if (S_ISBLK(mode)) {
+        return "blockSpecial";
+    }
+#endif
+#ifdef S_ISFIFO
+    else if (S_ISFIFO(mode)) {
+        return "fifo";
+    }
+#endif
+#ifdef S_ISLNK
+    else if (S_ISLNK(mode)) {
+        return "link";
+    }
+#endif
+#ifdef S_ISSOCK
+    else if (S_ISSOCK(mode)) {
+        return "socket";
+    }
+#endif
+    return "unknown";
+}
+
+
+static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
+    jim_wide value)
+{
+    Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
+    Jim_Obj *valobj = Jim_NewWideObj(interp, value);
+
+    if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
+        Jim_FreeObj(interp, nameobj);
+        Jim_FreeObj(interp, valobj);
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
+    const char *value)
+{
+    Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
+    Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
+
+    if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
+        Jim_FreeObj(interp, nameobj);
+        Jim_FreeObj(interp, valobj);
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
+{
+    if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
+        Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
+        return JIM_ERR;
+    }
+    set_array_int_value(interp, varName, "ino", sb->st_ino);
+    set_array_int_value(interp, varName, "mode", sb->st_mode);
+    set_array_int_value(interp, varName, "nlink", sb->st_nlink);
+    set_array_int_value(interp, varName, "uid", sb->st_uid);
+    set_array_int_value(interp, varName, "gid", sb->st_gid);
+    set_array_int_value(interp, varName, "size", sb->st_size);
+    set_array_int_value(interp, varName, "atime", sb->st_atime);
+    set_array_int_value(interp, varName, "mtime", sb->st_mtime);
+    set_array_int_value(interp, varName, "ctime", sb->st_ctime);
+    set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
+
+    
+    Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
+
+    return JIM_OK;
+}
+
+static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *path = Jim_String(argv[0]);
+    const char *p = strrchr(path, '/');
+
+    if (!p && path[0] == '.' && path[1] == '.' && path[2] == '\0') {
+        Jim_SetResultString(interp, "..", -1);
+    } else if (!p) {
+        Jim_SetResultString(interp, ".", -1);
+    }
+    else if (p == path) {
+        Jim_SetResultString(interp, "/", -1);
+    }
+#if defined(__MINGW32__) || defined(_MSC_VER)
+    else if (p[-1] == ':') {
+        
+        Jim_SetResultString(interp, path, p - path + 1);
+    }
+#endif
+    else {
+        Jim_SetResultString(interp, path, p - path);
+    }
+    return JIM_OK;
+}
+
+static int file_cmd_rootname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *path = Jim_String(argv[0]);
+    const char *lastSlash = strrchr(path, '/');
+    const char *p = strrchr(path, '.');
+
+    if (p == NULL || (lastSlash != NULL && lastSlash > p)) {
+        Jim_SetResult(interp, argv[0]);
+    }
+    else {
+        Jim_SetResultString(interp, path, p - path);
+    }
+    return JIM_OK;
+}
+
+static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *path = Jim_String(argv[0]);
+    const char *lastSlash = strrchr(path, '/');
+    const char *p = strrchr(path, '.');
+
+    if (p == NULL || (lastSlash != NULL && lastSlash >= p)) {
+        p = "";
+    }
+    Jim_SetResultString(interp, p, -1);
+    return JIM_OK;
+}
+
+static int file_cmd_tail(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *path = Jim_String(argv[0]);
+    const char *lastSlash = strrchr(path, '/');
+
+    if (lastSlash) {
+        Jim_SetResultString(interp, lastSlash + 1, -1);
+    }
+    else {
+        Jim_SetResult(interp, argv[0]);
+    }
+    return JIM_OK;
+}
+
+static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+#ifdef HAVE_REALPATH
+    const char *path = Jim_String(argv[0]);
+    char *newname = Jim_Alloc(MAXPATHLEN + 1);
+
+    if (realpath(path, newname)) {
+        Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1));
+        return JIM_OK;
+    }
+    else {
+        Jim_Free(newname);
+        Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno));
+        return JIM_ERR;
+    }
+#else
+    Jim_SetResultString(interp, "Not implemented", -1);
+    return JIM_ERR;
+#endif
+}
+
+static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int i;
+    char *newname = Jim_Alloc(MAXPATHLEN + 1);
+    char *last = newname;
+
+    *newname = 0;
+
+    
+    for (i = 0; i < argc; i++) {
+        int len;
+        const char *part = Jim_GetString(argv[i], &len);
+
+        if (*part == '/') {
+            
+            last = newname;
+        }
+#if defined(__MINGW32__) || defined(_MSC_VER)
+        else if (strchr(part, ':')) {
+            
+            last = newname;
+        }
+#endif
+        else if (part[0] == '.') {
+            if (part[1] == '/') {
+                part += 2;
+                len -= 2;
+            }
+            else if (part[1] == 0 && last != newname) {
+                
+                continue;
+            }
+        }
+
+        
+        if (last != newname && last[-1] != '/') {
+            *last++ = '/';
+        }
+
+        if (len) {
+            if (last + len - newname >= MAXPATHLEN) {
+                Jim_Free(newname);
+                Jim_SetResultString(interp, "Path too long", -1);
+                return JIM_ERR;
+            }
+            memcpy(last, part, len);
+            last += len;
+        }
+
+        
+        if (last > newname + 1 && last[-1] == '/') {
+            *--last = 0;
+        }
+    }
+
+    *last = 0;
+
+    
+
+    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname));
+
+    return JIM_OK;
+}
+
+static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
+{
+    const char *path = Jim_String(filename);
+    int rc = access(path, mode);
+
+    Jim_SetResultBool(interp, rc != -1);
+
+    return JIM_OK;
+}
+
+static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return file_access(interp, argv[0], R_OK);
+}
+
+static int file_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return file_access(interp, argv[0], W_OK);
+}
+
+static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+#ifdef X_OK
+    return file_access(interp, argv[0], X_OK);
+#else
+    Jim_SetResultBool(interp, 1);
+    return JIM_OK;
+#endif
+}
+
+static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return file_access(interp, argv[0], F_OK);
+}
+
+static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int force = Jim_CompareStringImmediate(interp, argv[0], "-force");
+
+    if (force || Jim_CompareStringImmediate(interp, argv[0], "--")) {
+        argc++;
+        argv--;
+    }
+
+    while (argc--) {
+        const char *path = Jim_String(argv[0]);
+
+        if (unlink(path) == -1 && errno != ENOENT) {
+            if (rmdir(path) == -1) {
+                
+                if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) {
+                    Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path,
+                        strerror(errno));
+                    return JIM_ERR;
+                }
+            }
+        }
+        argv++;
+    }
+    return JIM_OK;
+}
+
+#ifdef HAVE_MKDIR_ONE_ARG
+#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME)
+#else
+#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME, 0755)
+#endif
+
+static int mkdir_all(char *path)
+{
+    int ok = 1;
+
+    
+    goto first;
+
+    while (ok--) {
+        
+        {
+            char *slash = strrchr(path, '/');
+
+            if (slash && slash != path) {
+                *slash = 0;
+                if (mkdir_all(path) != 0) {
+                    return -1;
+                }
+                *slash = '/';
+            }
+        }
+      first:
+        if (MKDIR_DEFAULT(path) == 0) {
+            return 0;
+        }
+        if (errno == ENOENT) {
+            
+            continue;
+        }
+        
+        if (errno == EEXIST) {
+            struct stat sb;
+
+            if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+                return 0;
+            }
+            
+            errno = EEXIST;
+        }
+        
+        break;
+    }
+    return -1;
+}
+
+static int file_cmd_mkdir(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    while (argc--) {
+        char *path = Jim_StrDup(Jim_String(argv[0]));
+        int rc = mkdir_all(path);
+
+        Jim_Free(path);
+        if (rc != 0) {
+            Jim_SetResultFormatted(interp, "can't create directory \"%#s\": %s", argv[0],
+                strerror(errno));
+            return JIM_ERR;
+        }
+        argv++;
+    }
+    return JIM_OK;
+}
+
+#ifdef HAVE_MKSTEMP
+static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int fd;
+    char *filename;
+    const char *template = "/tmp/tcl.tmp.XXXXXX";
+
+    if (argc >= 1) {
+        template = Jim_String(argv[0]);
+    }
+    filename = Jim_StrDup(template);
+
+    fd = mkstemp(filename);
+    if (fd < 0) {
+        Jim_SetResultString(interp, "Failed to create tempfile", -1);
+        return JIM_ERR;
+    }
+    close(fd);
+
+    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
+    return JIM_OK;
+}
+#endif
+
+static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *source;
+    const char *dest;
+    int force = 0;
+
+    if (argc == 3) {
+        if (!Jim_CompareStringImmediate(interp, argv[0], "-force")) {
+            return -1;
+        }
+        force++;
+        argv++;
+        argc--;
+    }
+
+    source = Jim_String(argv[0]);
+    dest = Jim_String(argv[1]);
+
+    if (!force && access(dest, F_OK) == 0) {
+        Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": target exists", argv[0],
+            argv[1]);
+        return JIM_ERR;
+    }
+
+    if (rename(source, dest) != 0) {
+        Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": %s", argv[0], argv[1],
+            strerror(errno));
+        return JIM_ERR;
+    }
+
+    return JIM_OK;
+}
+
+static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
+{
+    const char *path = Jim_String(filename);
+
+    if (stat(path, sb) == -1) {
+        Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+#ifndef HAVE_LSTAT
+#define lstat stat
+#endif
+
+static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
+{
+    const char *path = Jim_String(filename);
+
+    if (lstat(path, sb) == -1) {
+        Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno));
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+
+    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResultInt(interp, sb.st_atime);
+    return JIM_OK;
+}
+
+static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+
+    if (argc == 2) {
+#ifdef HAVE_UTIMES
+        jim_wide newtime;
+        struct timeval times[2];
+
+        if (Jim_GetWide(interp, argv[1], &newtime) != JIM_OK) {
+            return JIM_ERR;
+        }
+
+        times[1].tv_sec = times[0].tv_sec = newtime;
+        times[1].tv_usec = times[0].tv_usec = 0;
+
+        if (utimes(Jim_String(argv[0]), times) != 0) {
+            Jim_SetResultFormatted(interp, "can't set time on \"%#s\": %s", argv[0], strerror(errno));
+            return JIM_ERR;
+        }
+#else
+        Jim_SetResultString(interp, "Not implemented", -1);
+        return JIM_ERR;
+#endif
+    }
+    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResultInt(interp, sb.st_mtime);
+    return JIM_OK;
+}
+
+static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return Jim_EvalPrefix(interp, "file copy", argc, argv);
+}
+
+static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+
+    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResultInt(interp, sb.st_size);
+    return JIM_OK;
+}
+
+static int file_cmd_isdirectory(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+    int ret = 0;
+
+    if (file_stat(interp, argv[0], &sb) == JIM_OK) {
+        ret = S_ISDIR(sb.st_mode);
+    }
+    Jim_SetResultInt(interp, ret);
+    return JIM_OK;
+}
+
+static int file_cmd_isfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+    int ret = 0;
+
+    if (file_stat(interp, argv[0], &sb) == JIM_OK) {
+        ret = S_ISREG(sb.st_mode);
+    }
+    Jim_SetResultInt(interp, ret);
+    return JIM_OK;
+}
+
+#ifdef HAVE_GETEUID
+static int file_cmd_owned(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+    int ret = 0;
+
+    if (file_stat(interp, argv[0], &sb) == JIM_OK) {
+        ret = (geteuid() == sb.st_uid);
+    }
+    Jim_SetResultInt(interp, ret);
+    return JIM_OK;
+}
+#endif
+
+#if defined(HAVE_READLINK)
+static int file_cmd_readlink(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *path = Jim_String(argv[0]);
+    char *linkValue = Jim_Alloc(MAXPATHLEN + 1);
+
+    int linkLength = readlink(path, linkValue, MAXPATHLEN);
+
+    if (linkLength == -1) {
+        Jim_Free(linkValue);
+        Jim_SetResultFormatted(interp, "couldn't readlink \"%#s\": %s", argv[0], strerror(errno));
+        return JIM_ERR;
+    }
+    linkValue[linkLength] = 0;
+    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, linkValue, linkLength));
+    return JIM_OK;
+}
+#endif
+
+static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+
+    if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1);
+    return JIM_OK;
+}
+
+static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+
+    if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
+        return JIM_ERR;
+    }
+    return StoreStatData(interp, argv[1], &sb);
+}
+
+static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct stat sb;
+
+    if (file_stat(interp, argv[0], &sb) != JIM_OK) {
+        return JIM_ERR;
+    }
+    return StoreStatData(interp, argv[1], &sb);
+}
+
+static const jim_subcmd_type file_command_table[] = {
+    {   "atime",
+        "name",
+        file_cmd_atime,
+        1,
+        1,
+        
+    },
+    {   "mtime",
+        "name ?time?",
+        file_cmd_mtime,
+        1,
+        2,
+        
+    },
+    {   "copy",
+        "?-force? source dest",
+        file_cmd_copy,
+        2,
+        3,
+        
+    },
+    {   "dirname",
+        "name",
+        file_cmd_dirname,
+        1,
+        1,
+        
+    },
+    {   "rootname",
+        "name",
+        file_cmd_rootname,
+        1,
+        1,
+        
+    },
+    {   "extension",
+        "name",
+        file_cmd_extension,
+        1,
+        1,
+        
+    },
+    {   "tail",
+        "name",
+        file_cmd_tail,
+        1,
+        1,
+        
+    },
+    {   "normalize",
+        "name",
+        file_cmd_normalize,
+        1,
+        1,
+        
+    },
+    {   "join",
+        "name ?name ...?",
+        file_cmd_join,
+        1,
+        -1,
+        
+    },
+    {   "readable",
+        "name",
+        file_cmd_readable,
+        1,
+        1,
+        
+    },
+    {   "writable",
+        "name",
+        file_cmd_writable,
+        1,
+        1,
+        
+    },
+    {   "executable",
+        "name",
+        file_cmd_executable,
+        1,
+        1,
+        
+    },
+    {   "exists",
+        "name",
+        file_cmd_exists,
+        1,
+        1,
+        
+    },
+    {   "delete",
+        "?-force|--? name ...",
+        file_cmd_delete,
+        1,
+        -1,
+        
+    },
+    {   "mkdir",
+        "dir ...",
+        file_cmd_mkdir,
+        1,
+        -1,
+        
+    },
+#ifdef HAVE_MKSTEMP
+    {   "tempfile",
+        "?template?",
+        file_cmd_tempfile,
+        0,
+        1,
+        
+    },
+#endif
+    {   "rename",
+        "?-force? source dest",
+        file_cmd_rename,
+        2,
+        3,
+        
+    },
+#if defined(HAVE_READLINK)
+    {   "readlink",
+        "name",
+        file_cmd_readlink,
+        1,
+        1,
+        
+    },
+#endif
+    {   "size",
+        "name",
+        file_cmd_size,
+        1,
+        1,
+        
+    },
+    {   "stat",
+        "name var",
+        file_cmd_stat,
+        2,
+        2,
+        
+    },
+    {   "lstat",
+        "name var",
+        file_cmd_lstat,
+        2,
+        2,
+        
+    },
+    {   "type",
+        "name",
+        file_cmd_type,
+        1,
+        1,
+        
+    },
+#ifdef HAVE_GETEUID
+    {   "owned",
+        "name",
+        file_cmd_owned,
+        1,
+        1,
+        
+    },
+#endif
+    {   "isdirectory",
+        "name",
+        file_cmd_isdirectory,
+        1,
+        1,
+        
+    },
+    {   "isfile",
+        "name",
+        file_cmd_isfile,
+        1,
+        1,
+        
+    },
+    {
+        NULL
+    }
+};
+
+static int Jim_CdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *path;
+
+    if (argc != 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "dirname");
+        return JIM_ERR;
+    }
+
+    path = Jim_String(argv[1]);
+
+    if (chdir(path) != 0) {
+        Jim_SetResultFormatted(interp, "couldn't change working directory to \"%s\": %s", path,
+            strerror(errno));
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const int cwd_len = 2048;
+    char *cwd = malloc(cwd_len);
+
+    if (getcwd(cwd, cwd_len) == NULL) {
+        Jim_SetResultString(interp, "Failed to get pwd", -1);
+        return JIM_ERR;
+    }
+#if defined(__MINGW32__) || defined(_MSC_VER)
+    {
+        
+        char *p = cwd;
+        while ((p = strchr(p, '\\')) != NULL) {
+            *p++ = '/';
+        }
+    }
+#endif
+
+    Jim_SetResultString(interp, cwd, -1);
+
+    free(cwd);
+    return JIM_OK;
+}
+
+int Jim_fileInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "file", Jim_SubCmdProc, (void *)file_command_table, NULL);
+    Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
+    Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
+    return JIM_OK;
+}
+
+#include <string.h>
+#include <ctype.h>
+
+
+#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
+static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp);
+    int i, j;
+    int rc;
+
+    
+    for (i = 1; i < argc; i++) {
+        int len;
+        const char *arg = Jim_GetString(argv[i], &len);
+
+        if (i > 1) {
+            Jim_AppendString(interp, cmdlineObj, " ", 1);
+        }
+        if (strpbrk(arg, "\\\" ") == NULL) {
+            
+            Jim_AppendString(interp, cmdlineObj, arg, len);
+            continue;
+        }
+
+        Jim_AppendString(interp, cmdlineObj, "\"", 1);
+        for (j = 0; j < len; j++) {
+            if (arg[j] == '\\' || arg[j] == '"') {
+                Jim_AppendString(interp, cmdlineObj, "\\", 1);
+            }
+            Jim_AppendString(interp, cmdlineObj, &arg[j], 1);
+        }
+        Jim_AppendString(interp, cmdlineObj, "\"", 1);
+    }
+    rc = system(Jim_String(cmdlineObj));
+
+    Jim_FreeNewObj(interp, cmdlineObj);
+
+    if (rc) {
+        Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
+        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, 0));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, rc));
+        Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
+        return JIM_ERR;
+    }
+
+    return JIM_OK;
+}
+
+int Jim_execInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
+    return JIM_OK;
+}
+#else
+
+
+#include <errno.h>
+#include <signal.h>
+
+#if defined(__MINGW32__)
+    
+    #ifndef STRICT
+    #define STRICT
+    #endif
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
+    #include <fcntl.h>
+
+    typedef HANDLE fdtype;
+    typedef HANDLE pidtype;
+    #define JIM_BAD_FD INVALID_HANDLE_VALUE
+    #define JIM_BAD_PID INVALID_HANDLE_VALUE
+    #define JimCloseFd CloseHandle
+
+    #define WIFEXITED(STATUS) 1
+    #define WEXITSTATUS(STATUS) (STATUS)
+    #define WIFSIGNALED(STATUS) 0
+    #define WTERMSIG(STATUS) 0
+    #define WNOHANG 1
+
+    static fdtype JimFileno(FILE *fh);
+    static pidtype JimWaitPid(pidtype pid, int *status, int nohang);
+    static fdtype JimDupFd(fdtype infd);
+    static fdtype JimOpenForRead(const char *filename);
+    static FILE *JimFdOpenForRead(fdtype fd);
+    static int JimPipe(fdtype pipefd[2]);
+    static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env,
+        fdtype inputId, fdtype outputId, fdtype errorId);
+    static int JimErrno(void);
+#else
+    #include <unistd.h>
+    #include <fcntl.h>
+    #include <sys/wait.h>
+
+    typedef int fdtype;
+    typedef int pidtype;
+    #define JimPipe pipe
+    #define JimErrno() errno
+    #define JIM_BAD_FD -1
+    #define JIM_BAD_PID -1
+    #define JimFileno fileno
+    #define JimReadFd read
+    #define JimCloseFd close
+    #define JimWaitPid waitpid
+    #define JimDupFd dup
+    #define JimFdOpenForRead(FD) fdopen((FD), "r")
+    #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0)
+
+    #ifndef HAVE_EXECVPE
+        #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
+    #endif
+#endif
+
+static const char *JimStrError(void);
+static char **JimSaveEnv(char **env);
+static void JimRestoreEnv(char **env);
+static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
+    pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
+static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
+static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
+static fdtype JimOpenForWrite(const char *filename, int append);
+static int JimRewindFd(fdtype fd);
+
+static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
+{
+    Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError());
+}
+
+static const char *JimStrError(void)
+{
+    return strerror(JimErrno());
+}
+
+static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
+{
+    int len;
+    const char *s = Jim_GetString(objPtr, &len);
+
+    if (len > 0 && s[len - 1] == '\n') {
+        objPtr->length--;
+        objPtr->bytes[objPtr->length] = '\0';
+    }
+}
+
+static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj)
+{
+    char buf[256];
+    FILE *fh = JimFdOpenForRead(fd);
+    if (fh == NULL) {
+        return JIM_ERR;
+    }
+
+    while (1) {
+        int retval = fread(buf, 1, sizeof(buf), fh);
+        if (retval > 0) {
+            Jim_AppendString(interp, strObj, buf, retval);
+        }
+        if (retval != sizeof(buf)) {
+            break;
+        }
+    }
+    Jim_RemoveTrailingNewline(strObj);
+    fclose(fh);
+    return JIM_OK;
+}
+
+static void JimTrimTrailingNewline(Jim_Interp *interp)
+{
+    int len;
+    const char *p = Jim_GetString(Jim_GetResult(interp), &len);
+
+    if (len > 0 && p[len - 1] == '\n') {
+        Jim_SetResultString(interp, p, len - 1);
+    }
+}
+
+static char **JimBuildEnv(Jim_Interp *interp)
+{
+#if defined(jim_ext_tclcompat)
+    int i;
+    int size;
+    int num;
+    int n;
+    char **envptr;
+    char *envdata;
+
+    Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE);
+
+    if (!objPtr) {
+        return Jim_GetEnviron();
+    }
+
+
+    
+    num = Jim_ListLength(interp, objPtr);
+    if (num % 2) {
+        num--;
+    }
+    size = Jim_Length(objPtr) + 2;
+
+    envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
+    envdata = (char *)&envptr[num / 2 + 1];
+
+    n = 0;
+    for (i = 0; i < num; i += 2) {
+        const char *s1, *s2;
+        Jim_Obj *elemObj;
+
+        Jim_ListIndex(interp, objPtr, i, &elemObj, JIM_NONE);
+        s1 = Jim_String(elemObj);
+        Jim_ListIndex(interp, objPtr, i + 1, &elemObj, JIM_NONE);
+        s2 = Jim_String(elemObj);
+
+        envptr[n] = envdata;
+        envdata += sprintf(envdata, "%s=%s", s1, s2);
+        envdata++;
+        n++;
+    }
+    envptr[n] = NULL;
+    *envdata = 0;
+
+    return envptr;
+#else
+    return Jim_GetEnviron();
+#endif
+}
+
+static void JimFreeEnv(char **env, char **original_environ)
+{
+#ifdef jim_ext_tclcompat
+    if (env != original_environ) {
+        Jim_Free(env);
+    }
+#endif
+}
+
+static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
+{
+    Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
+    int rc = JIM_ERR;
+
+    if (WIFEXITED(waitStatus)) {
+        if (WEXITSTATUS(waitStatus) == 0) {
+            Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1));
+            rc = JIM_OK;
+        }
+        else {
+            Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
+            Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
+            Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
+        }
+    }
+    else {
+        const char *type;
+        const char *action;
+
+        if (WIFSIGNALED(waitStatus)) {
+            type = "CHILDKILLED";
+            action = "killed";
+        }
+        else {
+            type = "CHILDSUSP";
+            action = "suspended";
+        }
+
+        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1));
+
+#ifdef jim_ext_signal
+        Jim_SetResultFormatted(interp, "child %s by signal %s", action, Jim_SignalId(WTERMSIG(waitStatus)));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1));
+#else
+        Jim_SetResultFormatted(interp, "child %s by signal %d", action, WTERMSIG(waitStatus));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus)));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
+        Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus)));
+#endif
+    }
+    Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
+    return rc;
+}
+
+
+struct WaitInfo
+{
+    pidtype pid;                    
+    int status;                 
+    int flags;                  
+};
+
+struct WaitInfoTable {
+    struct WaitInfo *info;
+    int size;
+    int used;
+};
+
+
+#define WI_DETACHED 2
+
+#define WAIT_TABLE_GROW_BY 4
+
+static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData)
+{
+    struct WaitInfoTable *table = privData;
+
+    Jim_Free(table->info);
+    Jim_Free(table);
+}
+
+static struct WaitInfoTable *JimAllocWaitInfoTable(void)
+{
+    struct WaitInfoTable *table = Jim_Alloc(sizeof(*table));
+    table->info = NULL;
+    table->size = table->used = 0;
+
+    return table;
+}
+
+static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    fdtype outputId;               /* File id for output pipe.  -1
+                                 * means command overrode. */
+    fdtype errorId;                /* File id for temporary file
+                                 * containing error output. */
+    pidtype *pidPtr;
+    int numPids, result;
+
+    if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
+        Jim_Obj *listObj;
+        int i;
+
+        argc--;
+        numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
+        if (numPids < 0) {
+            return JIM_ERR;
+        }
+        
+        listObj = Jim_NewListObj(interp, NULL, 0);
+        for (i = 0; i < numPids; i++) {
+            Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i]));
+        }
+        Jim_SetResult(interp, listObj);
+        JimDetachPids(interp, numPids, pidPtr);
+        Jim_Free(pidPtr);
+        return JIM_OK;
+    }
+
+    numPids =
+        JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId);
+
+    if (numPids < 0) {
+        return JIM_ERR;
+    }
+
+    Jim_SetResultString(interp, "", 0);
+
+    result = JIM_OK;
+    if (outputId != JIM_BAD_FD) {
+        result = JimAppendStreamToString(interp, outputId, Jim_GetResult(interp));
+        if (result < 0) {
+            Jim_SetResultErrno(interp, "error reading from output pipe");
+        }
+    }
+
+    if (JimCleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) {
+        result = JIM_ERR;
+    }
+    return result;
+}
+
+static void JimReapDetachedPids(struct WaitInfoTable *table)
+{
+    struct WaitInfo *waitPtr;
+    int count;
+
+    if (!table) {
+        return;
+    }
+
+    for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
+        if (waitPtr->flags & WI_DETACHED) {
+            int status;
+            pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
+            if (pid != JIM_BAD_PID) {
+                if (waitPtr != &table->info[table->used - 1]) {
+                    *waitPtr = table->info[table->used - 1];
+                }
+                table->used--;
+            }
+        }
+    }
+}
+
+static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr)
+{
+    int i;
+
+    
+    for (i = 0; i < table->used; i++) {
+        if (pid == table->info[i].pid) {
+            
+            JimWaitPid(pid, statusPtr, 0);
+
+            
+            if (i != table->used - 1) {
+                table->info[i] = table->info[table->used - 1];
+            }
+            table->used--;
+            return pid;
+        }
+    }
+
+    
+    return JIM_BAD_PID;
+}
+
+
+static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
+{
+    int j;
+    struct WaitInfoTable *table = Jim_CmdPrivData(interp);
+
+    for (j = 0; j < numPids; j++) {
+        
+        int i;
+        for (i = 0; i < table->used; i++) {
+            if (pidPtr[j] == table->info[i].pid) {
+                table->info[i].flags |= WI_DETACHED;
+                break;
+            }
+        }
+    }
+}
+
+static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name)
+{
+    FILE *fh;
+    Jim_Obj *fhObj;
+
+    fhObj = Jim_NewStringObj(interp, name, -1);
+    Jim_IncrRefCount(fhObj);
+    fh = Jim_AioFilehandle(interp, fhObj);
+    Jim_DecrRefCount(interp, fhObj);
+
+    return fh;
+}
+
+static int
+JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr,
+    fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr)
+{
+    pidtype *pidPtr = NULL;         /* Points to malloc-ed array holding all
+                                 * the pids of child processes. */
+    int numPids = 0;            /* Actual number of processes that exist
+                                 * at *pidPtr right now. */
+    int cmdCount;               /* Count of number of distinct commands
+                                 * found in argc/argv. */
+    const char *input = NULL;   /* Describes input for pipeline, depending
+                                 * on "inputFile".  NULL means take input
+                                 * from stdin/pipe. */
+    int input_len = 0;          
+
+#define FILE_NAME   0           
+#define FILE_APPEND 1           
+#define FILE_HANDLE 2           
+#define FILE_TEXT   3           
+
+    int inputFile = FILE_NAME;  /* 1 means input is name of input file.
+                                 * 2 means input is filehandle name.
+                                 * 0 means input holds actual
+                                 * text to be input to command. */
+
+    int outputFile = FILE_NAME; /* 0 means output is the name of output file.
+                                 * 1 means output is the name of output file, and append.
+                                 * 2 means output is filehandle name.
+                                 * All this is ignored if output is NULL
+                                 */
+    int errorFile = FILE_NAME;  /* 0 means error is the name of error file.
+                                 * 1 means error is the name of error file, and append.
+                                 * 2 means error is filehandle name.
+                                 * All this is ignored if error is NULL
+                                 */
+    const char *output = NULL;  /* Holds name of output file to pipe to,
+                                 * or NULL if output goes to stdout/pipe. */
+    const char *error = NULL;   /* Holds name of stderr file to pipe to,
+                                 * or NULL if stderr goes to stderr/pipe. */
+    fdtype inputId = JIM_BAD_FD;
+    fdtype outputId = JIM_BAD_FD;
+    fdtype errorId = JIM_BAD_FD;
+    fdtype lastOutputId = JIM_BAD_FD;
+    fdtype pipeIds[2];           
+    int firstArg, lastArg;      /* Indexes of first and last arguments in
+                                 * current command. */
+    int lastBar;
+    int i;
+    pidtype pid;
+    char **save_environ;
+    struct WaitInfoTable *table = Jim_CmdPrivData(interp);
+
+    
+    char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
+    int arg_count = 0;
+
+    JimReapDetachedPids(table);
+
+    if (inPipePtr != NULL) {
+        *inPipePtr = JIM_BAD_FD;
+    }
+    if (outPipePtr != NULL) {
+        *outPipePtr = JIM_BAD_FD;
+    }
+    if (errFilePtr != NULL) {
+        *errFilePtr = JIM_BAD_FD;
+    }
+    pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+
+    cmdCount = 1;
+    lastBar = -1;
+    for (i = 0; i < argc; i++) {
+        const char *arg = Jim_String(argv[i]);
+
+        if (arg[0] == '<') {
+            inputFile = FILE_NAME;
+            input = arg + 1;
+            if (*input == '<') {
+                inputFile = FILE_TEXT;
+                input_len = Jim_Length(argv[i]) - 2;
+                input++;
+            }
+            else if (*input == '@') {
+                inputFile = FILE_HANDLE;
+                input++;
+            }
+
+            if (!*input && ++i < argc) {
+                input = Jim_GetString(argv[i], &input_len);
+            }
+        }
+        else if (arg[0] == '>') {
+            int dup_error = 0;
+
+            outputFile = FILE_NAME;
+
+            output = arg + 1;
+            if (*output == '>') {
+                outputFile = FILE_APPEND;
+                output++;
+            }
+            if (*output == '&') {
+                
+                output++;
+                dup_error = 1;
+            }
+            if (*output == '@') {
+                outputFile = FILE_HANDLE;
+                output++;
+            }
+            if (!*output && ++i < argc) {
+                output = Jim_String(argv[i]);
+            }
+            if (dup_error) {
+                errorFile = outputFile;
+                error = output;
+            }
+        }
+        else if (arg[0] == '2' && arg[1] == '>') {
+            error = arg + 2;
+            errorFile = FILE_NAME;
+
+            if (*error == '@') {
+                errorFile = FILE_HANDLE;
+                error++;
+            }
+            else if (*error == '>') {
+                errorFile = FILE_APPEND;
+                error++;
+            }
+            if (!*error && ++i < argc) {
+                error = Jim_String(argv[i]);
+            }
+        }
+        else {
+            if (strcmp(arg, "|") == 0 || strcmp(arg, "|&") == 0) {
+                if (i == lastBar + 1 || i == argc - 1) {
+                    Jim_SetResultString(interp, "illegal use of | or |& in command", -1);
+                    goto badargs;
+                }
+                lastBar = i;
+                cmdCount++;
+            }
+            
+            arg_array[arg_count++] = (char *)arg;
+            continue;
+        }
+
+        if (i >= argc) {
+            Jim_SetResultFormatted(interp, "can't specify \"%s\" as last word in command", arg);
+            goto badargs;
+        }
+    }
+
+    if (arg_count == 0) {
+        Jim_SetResultString(interp, "didn't specify command to execute", -1);
+badargs:
+        Jim_Free(arg_array);
+        return -1;
+    }
+
+    
+    save_environ = JimSaveEnv(JimBuildEnv(interp));
+
+    if (input != NULL) {
+        if (inputFile == FILE_TEXT) {
+            inputId = JimCreateTemp(interp, input, input_len);
+            if (inputId == JIM_BAD_FD) {
+                goto error;
+            }
+        }
+        else if (inputFile == FILE_HANDLE) {
+            
+            FILE *fh = JimGetAioFilehandle(interp, input);
+
+            if (fh == NULL) {
+                goto error;
+            }
+            inputId = JimDupFd(JimFileno(fh));
+        }
+        else {
+            inputId = JimOpenForRead(input);
+            if (inputId == JIM_BAD_FD) {
+                Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError());
+                goto error;
+            }
+        }
+    }
+    else if (inPipePtr != NULL) {
+        if (JimPipe(pipeIds) != 0) {
+            Jim_SetResultErrno(interp, "couldn't create input pipe for command");
+            goto error;
+        }
+        inputId = pipeIds[0];
+        *inPipePtr = pipeIds[1];
+        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+    }
+
+    if (output != NULL) {
+        if (outputFile == FILE_HANDLE) {
+            FILE *fh = JimGetAioFilehandle(interp, output);
+            if (fh == NULL) {
+                goto error;
+            }
+            fflush(fh);
+            lastOutputId = JimDupFd(JimFileno(fh));
+        }
+        else {
+            lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND);
+            if (lastOutputId == JIM_BAD_FD) {
+                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError());
+                goto error;
+            }
+        }
+    }
+    else if (outPipePtr != NULL) {
+        if (JimPipe(pipeIds) != 0) {
+            Jim_SetResultErrno(interp, "couldn't create output pipe");
+            goto error;
+        }
+        lastOutputId = pipeIds[1];
+        *outPipePtr = pipeIds[0];
+        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+    }
+    
+    if (error != NULL) {
+        if (errorFile == FILE_HANDLE) {
+            if (strcmp(error, "1") == 0) {
+                
+                if (lastOutputId != JIM_BAD_FD) {
+                    errorId = JimDupFd(lastOutputId);
+                }
+                else {
+                    
+                    error = "stdout";
+                }
+            }
+            if (errorId == JIM_BAD_FD) {
+                FILE *fh = JimGetAioFilehandle(interp, error);
+                if (fh == NULL) {
+                    goto error;
+                }
+                fflush(fh);
+                errorId = JimDupFd(JimFileno(fh));
+            }
+        }
+        else {
+            errorId = JimOpenForWrite(error, errorFile == FILE_APPEND);
+            if (errorId == JIM_BAD_FD) {
+                Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError());
+                goto error;
+            }
+        }
+    }
+    else if (errFilePtr != NULL) {
+        errorId = JimCreateTemp(interp, NULL, 0);
+        if (errorId == JIM_BAD_FD) {
+            goto error;
+        }
+        *errFilePtr = JimDupFd(errorId);
+    }
+
+
+    pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
+    for (i = 0; i < numPids; i++) {
+        pidPtr[i] = JIM_BAD_PID;
+    }
+    for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
+        int pipe_dup_err = 0;
+        fdtype origErrorId = errorId;
+
+        for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
+            if (arg_array[lastArg][0] == '|') {
+                if (arg_array[lastArg][1] == '&') {
+                    pipe_dup_err = 1;
+                }
+                break;
+            }
+        }
+        
+        arg_array[lastArg] = NULL;
+        if (lastArg == arg_count) {
+            outputId = lastOutputId;
+        }
+        else {
+            if (JimPipe(pipeIds) != 0) {
+                Jim_SetResultErrno(interp, "couldn't create pipe");
+                goto error;
+            }
+            outputId = pipeIds[1];
+        }
+
+        
+
+#ifdef __MINGW32__
+        pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId);
+        if (pid == JIM_BAD_PID) {
+            Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
+            goto error;
+        }
+#else
+        if (table->info == NULL) {
+            (void)signal(SIGPIPE, SIG_IGN);
+        }
+
+        
+        if (pipe_dup_err) {
+            errorId = outputId;
+        }
+
+        pid = vfork();
+        if (pid < 0) {
+            Jim_SetResultErrno(interp, "couldn't fork child process");
+            goto error;
+        }
+        if (pid == 0) {
+            
+
+            if (inputId != -1) dup2(inputId, 0);
+            if (outputId != -1) dup2(outputId, 1);
+            if (errorId != -1) dup2(errorId, 2);
+
+            for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) {
+                close(i);
+            }
+
+            execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
+
+            
+            fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
+            _exit(127);
+        }
+#endif
+
+        
+
+        if (table->used == table->size) {
+            table->size += WAIT_TABLE_GROW_BY;
+            table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info));
+        }
+
+        table->info[table->used].pid = pid;
+        table->info[table->used].flags = 0;
+        table->used++;
+
+        pidPtr[numPids] = pid;
+
+        
+        errorId = origErrorId;
+
+
+        if (inputId != JIM_BAD_FD) {
+            JimCloseFd(inputId);
+        }
+        if (outputId != JIM_BAD_FD) {
+            JimCloseFd(outputId);
+        }
+        inputId = pipeIds[0];
+        pipeIds[0] = pipeIds[1] = JIM_BAD_FD;
+    }
+    *pidArrayPtr = pidPtr;
+
+
+  cleanup:
+    if (inputId != JIM_BAD_FD) {
+        JimCloseFd(inputId);
+    }
+    if (lastOutputId != JIM_BAD_FD) {
+        JimCloseFd(lastOutputId);
+    }
+    if (errorId != JIM_BAD_FD) {
+        JimCloseFd(errorId);
+    }
+    Jim_Free(arg_array);
+
+    JimRestoreEnv(save_environ);
+
+    return numPids;
+
+
+  error:
+    if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) {
+        JimCloseFd(*inPipePtr);
+        *inPipePtr = JIM_BAD_FD;
+    }
+    if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) {
+        JimCloseFd(*outPipePtr);
+        *outPipePtr = JIM_BAD_FD;
+    }
+    if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) {
+        JimCloseFd(*errFilePtr);
+        *errFilePtr = JIM_BAD_FD;
+    }
+    if (pipeIds[0] != JIM_BAD_FD) {
+        JimCloseFd(pipeIds[0]);
+    }
+    if (pipeIds[1] != JIM_BAD_FD) {
+        JimCloseFd(pipeIds[1]);
+    }
+    if (pidPtr != NULL) {
+        for (i = 0; i < numPids; i++) {
+            if (pidPtr[i] != JIM_BAD_PID) {
+                JimDetachPids(interp, 1, &pidPtr[i]);
+            }
+        }
+        Jim_Free(pidPtr);
+    }
+    numPids = -1;
+    goto cleanup;
+}
+
+
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId)
+{
+    struct WaitInfoTable *table = Jim_CmdPrivData(interp);
+    int result = JIM_OK;
+    int i;
+
+    for (i = 0; i < numPids; i++) {
+        int waitStatus = 0;
+        if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
+            if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus) != JIM_OK) {
+                result = JIM_ERR;
+            }
+        }
+    }
+    Jim_Free(pidPtr);
+
+    if (errorId != JIM_BAD_FD) {
+        JimRewindFd(errorId);
+        if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
+            result = JIM_ERR;
+        }
+    }
+
+    JimTrimTrailingNewline(interp);
+
+    return result;
+}
+
+int Jim_execInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+    Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
+    return JIM_OK;
+}
+
+#if defined(__MINGW32__)
+
+
+static SECURITY_ATTRIBUTES *JimStdSecAttrs(void)
+{
+    static SECURITY_ATTRIBUTES secAtts;
+
+    secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
+    secAtts.lpSecurityDescriptor = NULL;
+    secAtts.bInheritHandle = TRUE;
+    return &secAtts;
+}
+
+static int JimErrno(void)
+{
+    switch (GetLastError()) {
+    case ERROR_FILE_NOT_FOUND: return ENOENT;
+    case ERROR_PATH_NOT_FOUND: return ENOENT;
+    case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
+    case ERROR_ACCESS_DENIED: return EACCES;
+    case ERROR_INVALID_HANDLE: return EBADF;
+    case ERROR_BAD_ENVIRONMENT: return E2BIG;
+    case ERROR_BAD_FORMAT: return ENOEXEC;
+    case ERROR_INVALID_ACCESS: return EACCES;
+    case ERROR_INVALID_DRIVE: return ENOENT;
+    case ERROR_CURRENT_DIRECTORY: return EACCES;
+    case ERROR_NOT_SAME_DEVICE: return EXDEV;
+    case ERROR_NO_MORE_FILES: return ENOENT;
+    case ERROR_WRITE_PROTECT: return EROFS;
+    case ERROR_BAD_UNIT: return ENXIO;
+    case ERROR_NOT_READY: return EBUSY;
+    case ERROR_BAD_COMMAND: return EIO;
+    case ERROR_CRC: return EIO;
+    case ERROR_BAD_LENGTH: return EIO;
+    case ERROR_SEEK: return EIO;
+    case ERROR_WRITE_FAULT: return EIO;
+    case ERROR_READ_FAULT: return EIO;
+    case ERROR_GEN_FAILURE: return EIO;
+    case ERROR_SHARING_VIOLATION: return EACCES;
+    case ERROR_LOCK_VIOLATION: return EACCES;
+    case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
+    case ERROR_HANDLE_DISK_FULL: return ENOSPC;
+    case ERROR_NOT_SUPPORTED: return ENODEV;
+    case ERROR_REM_NOT_LIST: return EBUSY;
+    case ERROR_DUP_NAME: return EEXIST;
+    case ERROR_BAD_NETPATH: return ENOENT;
+    case ERROR_NETWORK_BUSY: return EBUSY;
+    case ERROR_DEV_NOT_EXIST: return ENODEV;
+    case ERROR_TOO_MANY_CMDS: return EAGAIN;
+    case ERROR_ADAP_HDW_ERR: return EIO;
+    case ERROR_BAD_NET_RESP: return EIO;
+    case ERROR_UNEXP_NET_ERR: return EIO;
+    case ERROR_NETNAME_DELETED: return ENOENT;
+    case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
+    case ERROR_BAD_DEV_TYPE: return ENODEV;
+    case ERROR_BAD_NET_NAME: return ENOENT;
+    case ERROR_TOO_MANY_NAMES: return ENFILE;
+    case ERROR_TOO_MANY_SESS: return EIO;
+    case ERROR_SHARING_PAUSED: return EAGAIN;
+    case ERROR_REDIR_PAUSED: return EAGAIN;
+    case ERROR_FILE_EXISTS: return EEXIST;
+    case ERROR_CANNOT_MAKE: return ENOSPC;
+    case ERROR_OUT_OF_STRUCTURES: return ENFILE;
+    case ERROR_ALREADY_ASSIGNED: return EEXIST;
+    case ERROR_INVALID_PASSWORD: return EPERM;
+    case ERROR_NET_WRITE_FAULT: return EIO;
+    case ERROR_NO_PROC_SLOTS: return EAGAIN;
+    case ERROR_DISK_CHANGE: return EXDEV;
+    case ERROR_BROKEN_PIPE: return EPIPE;
+    case ERROR_OPEN_FAILED: return ENOENT;
+    case ERROR_DISK_FULL: return ENOSPC;
+    case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
+    case ERROR_INVALID_TARGET_HANDLE: return EBADF;
+    case ERROR_INVALID_NAME: return ENOENT;
+    case ERROR_PROC_NOT_FOUND: return ESRCH;
+    case ERROR_WAIT_NO_CHILDREN: return ECHILD;
+    case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
+    case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
+    case ERROR_SEEK_ON_DEVICE: return ESPIPE;
+    case ERROR_BUSY_DRIVE: return EAGAIN;
+    case ERROR_DIR_NOT_EMPTY: return EEXIST;
+    case ERROR_NOT_LOCKED: return EACCES;
+    case ERROR_BAD_PATHNAME: return ENOENT;
+    case ERROR_LOCK_FAILED: return EACCES;
+    case ERROR_ALREADY_EXISTS: return EEXIST;
+    case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
+    case ERROR_BAD_PIPE: return EPIPE;
+    case ERROR_PIPE_BUSY: return EAGAIN;
+    case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
+    case ERROR_DIRECTORY: return ENOTDIR;
+    }
+    return EINVAL;
+}
+
+static int JimPipe(fdtype pipefd[2])
+{
+    if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) {
+        return 0;
+    }
+    return -1;
+}
+
+static fdtype JimDupFd(fdtype infd)
+{
+    fdtype dupfd;
+    pidtype pid = GetCurrentProcess();
+
+    if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+        return dupfd;
+    }
+    return JIM_BAD_FD;
+}
+
+static int JimRewindFd(fdtype fd)
+{
+    return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0;
+}
+
+#if 0
+static int JimReadFd(fdtype fd, char *buffer, size_t len)
+{
+    DWORD num;
+
+    if (ReadFile(fd, buffer, len, &num, NULL)) {
+        return num;
+    }
+    if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) {
+        return 0;
+    }
+    return -1;
+}
+#endif
+
+static FILE *JimFdOpenForRead(fdtype fd)
+{
+    return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r");
+}
+
+static fdtype JimFileno(FILE *fh)
+{
+    return (fdtype)_get_osfhandle(_fileno(fh));
+}
+
+static fdtype JimOpenForRead(const char *filename)
+{
+    return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+        JimStdSecAttrs(), OPEN_EXISTING, 0, NULL);
+}
+
+static fdtype JimOpenForWrite(const char *filename, int append)
+{
+    return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+        JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL);
+}
+
+static FILE *JimFdOpenForWrite(fdtype fd)
+{
+    return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w");
+}
+
+static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
+{
+    DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
+    if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
+        
+        return JIM_BAD_PID;
+    }
+    GetExitCodeProcess(pid, &ret);
+    *status = ret;
+    CloseHandle(pid);
+    return pid;
+}
+
+static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
+{
+    char name[MAX_PATH];
+    HANDLE handle;
+
+    if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) {
+        return JIM_BAD_FD;
+    }
+
+    handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(),
+            CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+            NULL);
+
+    if (handle == INVALID_HANDLE_VALUE) {
+        goto error;
+    }
+
+    if (contents != NULL) {
+        
+        FILE *fh = JimFdOpenForWrite(JimDupFd(handle));
+        if (fh == NULL) {
+            goto error;
+        }
+
+        if (fwrite(contents, len, 1, fh) != 1) {
+            fclose(fh);
+            goto error;
+        }
+        fseek(fh, 0, SEEK_SET);
+        fclose(fh);
+    }
+    return handle;
+
+  error:
+    Jim_SetResultErrno(interp, "failed to create temp file");
+    CloseHandle(handle);
+    DeleteFile(name);
+    return JIM_BAD_FD;
+}
+
+static int
+JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH])
+{
+    int i;
+    static char extensions[][5] = {".exe", "", ".bat"};
+
+    for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {
+        lstrcpyn(fullPath, originalName, MAX_PATH - 5);
+        lstrcat(fullPath, extensions[i]);
+
+        if (SearchPath(NULL, fullPath, NULL, MAX_PATH, fullPath, NULL) == 0) {
+            continue;
+        }
+        if (GetFileAttributes(fullPath) & FILE_ATTRIBUTE_DIRECTORY) {
+            continue;
+        }
+        return 0;
+    }
+
+    return -1;
+}
+
+static char **JimSaveEnv(char **env)
+{
+    return env;
+}
+
+static void JimRestoreEnv(char **env)
+{
+    JimFreeEnv(env, Jim_GetEnviron());
+}
+
+static Jim_Obj *
+JimWinBuildCommandLine(Jim_Interp *interp, char **argv)
+{
+    char *start, *special;
+    int quote, i;
+
+    Jim_Obj *strObj = Jim_NewStringObj(interp, "", 0);
+
+    for (i = 0; argv[i]; i++) {
+        if (i > 0) {
+            Jim_AppendString(interp, strObj, " ", 1);
+        }
+
+        if (argv[i][0] == '\0') {
+            quote = 1;
+        }
+        else {
+            quote = 0;
+            for (start = argv[i]; *start != '\0'; start++) {
+                if (isspace(UCHAR(*start))) {
+                    quote = 1;
+                    break;
+                }
+            }
+        }
+        if (quote) {
+            Jim_AppendString(interp, strObj, "\"" , 1);
+        }
+
+        start = argv[i];
+        for (special = argv[i]; ; ) {
+            if ((*special == '\\') && (special[1] == '\\' ||
+                    special[1] == '"' || (quote && special[1] == '\0'))) {
+                Jim_AppendString(interp, strObj, start, special - start);
+                start = special;
+                while (1) {
+                    special++;
+                    if (*special == '"' || (quote && *special == '\0')) {
+
+                        Jim_AppendString(interp, strObj, start, special - start);
+                        break;
+                    }
+                    if (*special != '\\') {
+                        break;
+                    }
+                }
+                Jim_AppendString(interp, strObj, start, special - start);
+                start = special;
+            }
+            if (*special == '"') {
+        if (special == start) {
+            Jim_AppendString(interp, strObj, "\"", 1);
+        }
+        else {
+            Jim_AppendString(interp, strObj, start, special - start);
+        }
+                Jim_AppendString(interp, strObj, "\\\"", 2);
+                start = special + 1;
+            }
+            if (*special == '\0') {
+                break;
+            }
+            special++;
+        }
+        Jim_AppendString(interp, strObj, start, special - start);
+        if (quote) {
+            Jim_AppendString(interp, strObj, "\"", 1);
+        }
+    }
+    return strObj;
+}
+
+static pidtype
+JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId)
+{
+    STARTUPINFO startInfo;
+    PROCESS_INFORMATION procInfo;
+    HANDLE hProcess, h;
+    char execPath[MAX_PATH];
+    char *originalName;
+    pidtype pid = JIM_BAD_PID;
+    Jim_Obj *cmdLineObj;
+
+    if (JimWinFindExecutable(argv[0], execPath) < 0) {
+        return JIM_BAD_PID;
+    }
+    originalName = argv[0];
+    argv[0] = execPath;
+
+    hProcess = GetCurrentProcess();
+    cmdLineObj = JimWinBuildCommandLine(interp, argv);
+
+
+    ZeroMemory(&startInfo, sizeof(startInfo));
+    startInfo.cb = sizeof(startInfo);
+    startInfo.dwFlags   = STARTF_USESTDHANDLES;
+    startInfo.hStdInput        = INVALID_HANDLE_VALUE;
+    startInfo.hStdOutput= INVALID_HANDLE_VALUE;
+    startInfo.hStdError = INVALID_HANDLE_VALUE;
+
+    if (inputId == JIM_BAD_FD) {
+        if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) {
+            CloseHandle(h);
+        }
+    } else {
+        DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput,
+                0, TRUE, DUPLICATE_SAME_ACCESS);
+    }
+    if (startInfo.hStdInput == JIM_BAD_FD) {
+        goto end;
+    }
+
+    if (outputId == JIM_BAD_FD) {
+        startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0,
+                JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    } else {
+        DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput,
+                0, TRUE, DUPLICATE_SAME_ACCESS);
+    }
+    if (startInfo.hStdOutput == JIM_BAD_FD) {
+        goto end;
+    }
+
+    if (errorId == JIM_BAD_FD) {
+
+        startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0,
+                JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    } else {
+        DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError,
+                0, TRUE, DUPLICATE_SAME_ACCESS);
+    }
+    if (startInfo.hStdError == JIM_BAD_FD) {
+        goto end;
+    }
+
+    if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE,
+            0, env, NULL, &startInfo, &procInfo)) {
+        goto end;
+    }
+
+
+    WaitForInputIdle(procInfo.hProcess, 5000);
+    CloseHandle(procInfo.hThread);
+
+    pid = procInfo.hProcess;
+
+    end:
+    Jim_FreeNewObj(interp, cmdLineObj);
+    if (startInfo.hStdInput != JIM_BAD_FD) {
+        CloseHandle(startInfo.hStdInput);
+    }
+    if (startInfo.hStdOutput != JIM_BAD_FD) {
+        CloseHandle(startInfo.hStdOutput);
+    }
+    if (startInfo.hStdError != JIM_BAD_FD) {
+        CloseHandle(startInfo.hStdError);
+    }
+    return pid;
+}
+#else
+
+static int JimOpenForWrite(const char *filename, int append)
+{
+    return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
+}
+
+static int JimRewindFd(int fd)
+{
+    return lseek(fd, 0L, SEEK_SET);
+}
+
+static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
+{
+    char inName[] = "/tmp/tcl.tmp.XXXXXX";
+
+    int fd = mkstemp(inName);
+    if (fd == JIM_BAD_FD) {
+        Jim_SetResultErrno(interp, "couldn't create temp file");
+        return -1;
+    }
+    unlink(inName);
+    if (contents) {
+        if (write(fd, contents, len) != len) {
+            Jim_SetResultErrno(interp, "couldn't write temp file");
+            close(fd);
+            return -1;
+        }
+        lseek(fd, 0L, SEEK_SET);
+    }
+    return fd;
+}
+
+static char **JimSaveEnv(char **env)
+{
+    char **saveenv = Jim_GetEnviron();
+    Jim_SetEnviron(env);
+    return saveenv;
+}
+
+static void JimRestoreEnv(char **env)
+{
+    JimFreeEnv(Jim_GetEnviron(), env);
+    Jim_SetEnviron(env);
+}
+#endif
+#endif
+
+
+
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 500
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    
+    char buf[100];
+    time_t t;
+    long seconds;
+
+    const char *format = "%a %b  %d %H:%M:%S %Z %Y";
+
+    if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
+        return -1;
+    }
+
+    if (argc == 3) {
+        format = Jim_String(argv[2]);
+    }
+
+    if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) {
+        return JIM_ERR;
+    }
+    t = seconds;
+
+    strftime(buf, sizeof(buf), format, localtime(&t));
+
+    Jim_SetResultString(interp, buf, -1);
+
+    return JIM_OK;
+}
+
+#ifdef HAVE_STRPTIME
+static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    char *pt;
+    struct tm tm;
+    time_t now = time(0);
+
+    if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) {
+        return -1;
+    }
+
+    
+    localtime_r(&now, &tm);
+
+    pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm);
+    if (pt == 0 || *pt != 0) {
+        Jim_SetResultString(interp, "Failed to parse time according to format", -1);
+        return JIM_ERR;
+    }
+
+    
+    Jim_SetResultInt(interp, mktime(&tm));
+
+    return JIM_OK;
+}
+#endif
+
+static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_SetResultInt(interp, time(NULL));
+
+    return JIM_OK;
+}
+
+static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+
+    Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec);
+
+    return JIM_OK;
+}
+
+static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+
+    Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000);
+
+    return JIM_OK;
+}
+
+static const jim_subcmd_type clock_command_table[] = {
+    {   "seconds",
+        NULL,
+        clock_cmd_seconds,
+        0,
+        0,
+        
+    },
+    {   "clicks",
+        NULL,
+        clock_cmd_micros,
+        0,
+        0,
+        
+    },
+    {   "microseconds",
+        NULL,
+        clock_cmd_micros,
+        0,
+        0,
+        
+    },
+    {   "milliseconds",
+        NULL,
+        clock_cmd_millis,
+        0,
+        0,
+        
+    },
+    {   "format",
+        "seconds ?-format format?",
+        clock_cmd_format,
+        1,
+        3,
+        
+    },
+#ifdef HAVE_STRPTIME
+    {   "scan",
+        "str -format format",
+        clock_cmd_scan,
+        3,
+        3,
+        
+    },
+#endif
+    { NULL }
+};
+
+int Jim_clockInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
+    return JIM_OK;
+}
+
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    
+    Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
+    return JIM_OK;
+}
+
+static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
+
+    if (!objPtr) {
+        return JIM_OK;
+    }
+
+    if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
+        
+        if (Jim_IsList(objPtr)) {
+            if (Jim_ListLength(interp, objPtr) % 2 != 0) {
+                
+                return JIM_ERR;
+            }
+        }
+        else if (Jim_DictSize(interp, objPtr) < 0) {
+            
+            return JIM_ERR;
+        }
+        Jim_SetResult(interp, objPtr);
+        return JIM_OK;
+    }
+
+    
+    return Jim_DictValues(interp, objPtr, argv[1]);
+}
+
+static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
+
+    if (!objPtr) {
+        return JIM_OK;
+    }
+
+    return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]);
+}
+
+static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int i;
+    int len;
+    Jim_Obj *resultObj;
+    Jim_Obj *objPtr;
+    Jim_Obj **dictValuesObj;
+
+    if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
+        
+        Jim_UnsetVariable(interp, argv[0], JIM_NONE);
+        return JIM_OK;
+    }
+
+    objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
+
+    if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    
+    resultObj = Jim_NewDictObj(interp, NULL, 0);
+
+    for (i = 0; i < len; i += 2) {
+        if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
+            Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
+        }
+    }
+    Jim_Free(dictValuesObj);
+
+    Jim_SetVariable(interp, argv[0], resultObj);
+    return JIM_OK;
+}
+
+static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+    int len = 0;
+
+    
+    objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
+    if (objPtr) {
+        len = Jim_DictSize(interp, objPtr);
+        if (len < 0) {
+            return JIM_ERR;
+        }
+    }
+
+    Jim_SetResultInt(interp, len);
+
+    return JIM_OK;
+}
+
+static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int i;
+    int len;
+    Jim_Obj *listObj = argv[1];
+    Jim_Obj *dictObj;
+
+    len = Jim_ListLength(interp, listObj);
+    if (len % 2) {
+        Jim_SetResultString(interp, "list must have an even number of elements", -1);
+        return JIM_ERR;
+    }
+
+    dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
+    if (!dictObj) {
+        
+        return Jim_SetVariable(interp, argv[0], listObj);
+    }
+
+    if (Jim_IsShared(dictObj)) {
+        dictObj = Jim_DuplicateObj(interp, dictObj);
+    }
+
+    for (i = 0; i < len; i += 2) {
+        Jim_Obj *nameObj;
+        Jim_Obj *valueObj;
+
+        Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE);
+        Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE);
+
+        Jim_DictAddElement(interp, dictObj, nameObj, valueObj);
+    }
+    return Jim_SetVariable(interp, argv[0], dictObj);
+}
+
+static const jim_subcmd_type array_command_table[] = {
+        {       "exists",
+                "arrayName",
+                array_cmd_exists,
+                1,
+                1,
+                
+        },
+        {       "get",
+                "arrayName ?pattern?",
+                array_cmd_get,
+                1,
+                2,
+                
+        },
+        {       "names",
+                "arrayName ?pattern?",
+                array_cmd_names,
+                1,
+                2,
+                
+        },
+        {       "set",
+                "arrayName list",
+                array_cmd_set,
+                2,
+                2,
+                
+        },
+        {       "size",
+                "arrayName",
+                array_cmd_size,
+                1,
+                1,
+                
+        },
+        {       "unset",
+                "arrayName ?pattern?",
+                array_cmd_unset,
+                1,
+                2,
+                
+        },
+        {       NULL
+        }
+};
+
+int Jim_arrayInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
+    return JIM_OK;
+}
+int Jim_InitStaticExtensions(Jim_Interp *interp)
+{
+extern int Jim_bootstrapInit(Jim_Interp *);
+extern int Jim_aioInit(Jim_Interp *);
+extern int Jim_readdirInit(Jim_Interp *);
+extern int Jim_globInit(Jim_Interp *);
+extern int Jim_regexpInit(Jim_Interp *);
+extern int Jim_fileInit(Jim_Interp *);
+extern int Jim_execInit(Jim_Interp *);
+extern int Jim_clockInit(Jim_Interp *);
+extern int Jim_arrayInit(Jim_Interp *);
+extern int Jim_stdlibInit(Jim_Interp *);
+extern int Jim_tclcompatInit(Jim_Interp *);
+Jim_bootstrapInit(interp);
+Jim_aioInit(interp);
+Jim_readdirInit(interp);
+Jim_globInit(interp);
+Jim_regexpInit(interp);
+Jim_fileInit(interp);
+Jim_execInit(interp);
+Jim_clockInit(interp);
+Jim_arrayInit(interp);
+Jim_stdlibInit(interp);
+Jim_tclcompatInit(interp);
+return JIM_OK;
+}
+
+#define JIM_OPTIMIZATION        
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#include <assert.h>
+#include <errno.h>
+#include <time.h>
+#include <setjmp.h>
+
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
+#ifdef HAVE_CRT_EXTERNS_H
+#include <crt_externs.h>
+#endif
+
+
+#include <math.h>
+
+
+
+
+
+#ifndef TCL_LIBRARY
+#define TCL_LIBRARY "."
+#endif
+#ifndef TCL_PLATFORM_OS
+#define TCL_PLATFORM_OS "unknown"
+#endif
+#ifndef TCL_PLATFORM_PLATFORM
+#define TCL_PLATFORM_PLATFORM "unknown"
+#endif
+#ifndef TCL_PLATFORM_PATH_SEPARATOR
+#define TCL_PLATFORM_PATH_SEPARATOR ":"
+#endif
+
+
+
+
+
+
+
+#ifdef JIM_MAINTAINER
+#define JIM_DEBUG_COMMAND
+#define JIM_DEBUG_PANIC
+#endif
+
+
+
+#define JIM_INTEGER_SPACE 24
+
+const char *jim_tt_name(int type);
+
+#ifdef JIM_DEBUG_PANIC
+static void JimPanicDump(int panic_condition, const char *fmt, ...);
+#define JimPanic(X) JimPanicDump X
+#else
+#define JimPanic(X)
+#endif
+
+
+static char JimEmptyStringRep[] = "";
+
+static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
+static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
+    int flags);
+static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
+static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
+static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
+static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
+static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
+    const char *prefix, const char *const *tablePtr, const char *name);
+static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
+static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
+static int JimSign(jim_wide w);
+static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr);
+static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen);
+static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len);
+
+
+
+#define JimWideValue(objPtr) (objPtr)->internalRep.wideValue
+
+#define JimObjTypeName(O) ((O)->typePtr ? (O)->typePtr->name : "none")
+
+static int utf8_tounicode_case(const char *s, int *uc, int upper)
+{
+    int l = utf8_tounicode(s, uc);
+    if (upper) {
+        *uc = utf8_upper(*uc);
+    }
+    return l;
+}
+
+
+#define JIM_CHARSET_SCAN 2
+#define JIM_CHARSET_GLOB 0
+
+static const char *JimCharsetMatch(const char *pattern, int c, int flags)
+{
+    int not = 0;
+    int pchar;
+    int match = 0;
+    int nocase = 0;
+
+    if (flags & JIM_NOCASE) {
+        nocase++;
+        c = utf8_upper(c);
+    }
+
+    if (flags & JIM_CHARSET_SCAN) {
+        if (*pattern == '^') {
+            not++;
+            pattern++;
+        }
+
+        
+        if (*pattern == ']') {
+            goto first;
+        }
+    }
+
+    while (*pattern && *pattern != ']') {
+        
+        if (pattern[0] == '\\') {
+first:
+            pattern += utf8_tounicode_case(pattern, &pchar, nocase);
+        }
+        else {
+            
+            int start;
+            int end;
+
+            pattern += utf8_tounicode_case(pattern, &start, nocase);
+            if (pattern[0] == '-' && pattern[1]) {
+                
+                pattern += utf8_tounicode(pattern, &pchar);
+                pattern += utf8_tounicode_case(pattern, &end, nocase);
+
+                
+                if ((c >= start && c <= end) || (c >= end && c <= start)) {
+                    match = 1;
+                }
+                continue;
+            }
+            pchar = start;
+        }
+
+        if (pchar == c) {
+            match = 1;
+        }
+    }
+    if (not) {
+        match = !match;
+    }
+
+    return match ? pattern : NULL;
+}
+
+
+
+static int JimGlobMatch(const char *pattern, const char *string, int nocase)
+{
+    int c;
+    int pchar;
+    while (*pattern) {
+        switch (pattern[0]) {
+            case '*':
+                while (pattern[1] == '*') {
+                    pattern++;
+                }
+                pattern++;
+                if (!pattern[0]) {
+                    return 1;   
+                }
+                while (*string) {
+                    
+                    if (JimGlobMatch(pattern, string, nocase))
+                        return 1;       
+                    string += utf8_tounicode(string, &c);
+                }
+                return 0;       
+
+            case '?':
+                string += utf8_tounicode(string, &c);
+                break;
+
+            case '[': {
+                    string += utf8_tounicode(string, &c);
+                    pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0);
+                    if (!pattern) {
+                        return 0;
+                    }
+                    if (!*pattern) {
+                        
+                        continue;
+                    }
+                    break;
+                }
+            case '\\':
+                if (pattern[1]) {
+                    pattern++;
+                }
+                
+            default:
+                string += utf8_tounicode_case(string, &c, nocase);
+                utf8_tounicode_case(pattern, &pchar, nocase);
+                if (pchar != c) {
+                    return 0;
+                }
+                break;
+        }
+        pattern += utf8_tounicode_case(pattern, &pchar, nocase);
+        if (!*string) {
+            while (*pattern == '*') {
+                pattern++;
+            }
+            break;
+        }
+    }
+    if (!*pattern && !*string) {
+        return 1;
+    }
+    return 0;
+}
+
+static int JimStringCompare(const char *s1, int l1, const char *s2, int l2)
+{
+    if (l1 < l2) {
+        return memcmp(s1, s2, l1) <= 0 ? -1 : 1;
+    }
+    else if (l2 < l1) {
+        return memcmp(s1, s2, l2) >= 0 ? 1 : -1;
+    }
+    else {
+        return JimSign(memcmp(s1, s2, l1));
+    }
+}
+
+static int JimStringCompareLen(const char *s1, const char *s2, int maxchars, int nocase)
+{
+    while (*s1 && *s2 && maxchars) {
+        int c1, c2;
+        s1 += utf8_tounicode_case(s1, &c1, nocase);
+        s2 += utf8_tounicode_case(s2, &c2, nocase);
+        if (c1 != c2) {
+            return JimSign(c1 - c2);
+        }
+        maxchars--;
+    }
+    if (!maxchars) {
+        return 0;
+    }
+    
+    if (*s1) {
+        return 1;
+    }
+    if (*s2) {
+        return -1;
+    }
+    return 0;
+}
+
+static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int idx)
+{
+    int i;
+    int l1bytelen;
+
+    if (!l1 || !l2 || l1 > l2) {
+        return -1;
+    }
+    if (idx < 0)
+        idx = 0;
+    s2 += utf8_index(s2, idx);
+
+    l1bytelen = utf8_index(s1, l1);
+
+    for (i = idx; i <= l2 - l1; i++) {
+        int c;
+        if (memcmp(s2, s1, l1bytelen) == 0) {
+            return i;
+        }
+        s2 += utf8_tounicode(s2, &c);
+    }
+    return -1;
+}
+
+static int JimStringLast(const char *s1, int l1, const char *s2, int l2)
+{
+    const char *p;
+
+    if (!l1 || !l2 || l1 > l2)
+        return -1;
+
+    
+    for (p = s2 + l2 - 1; p != s2 - 1; p--) {
+        if (*p == *s1 && memcmp(s1, p, l1) == 0) {
+            return p - s2;
+        }
+    }
+    return -1;
+}
+
+#ifdef JIM_UTF8
+static int JimStringLastUtf8(const char *s1, int l1, const char *s2, int l2)
+{
+    int n = JimStringLast(s1, utf8_index(s1, l1), s2, utf8_index(s2, l2));
+    if (n > 0) {
+        n = utf8_strlen(s2, n);
+    }
+    return n;
+}
+#endif
+
+static int JimWideToString(char *buf, jim_wide wideValue)
+{
+    int pos = 0;
+
+    if (wideValue == 0) {
+        buf[pos++] = '0';
+    }
+    else {
+        char tmp[JIM_INTEGER_SPACE];
+        int num = 0;
+        int i;
+
+        if (wideValue < 0) {
+            buf[pos++] = '-';
+            
+            i = wideValue % 10;
+            tmp[num++] = (i > 0) ? (10 - i) : -i;
+            wideValue /= -10;
+        }
+
+        while (wideValue) {
+            tmp[num++] = wideValue % 10;
+            wideValue /= 10;
+        }
+
+        for (i = 0; i < num; i++) {
+            buf[pos++] = '0' + tmp[num - i - 1];
+        }
+    }
+    buf[pos] = 0;
+
+    return pos;
+}
+
+static int JimCheckConversion(const char *str, const char *endptr)
+{
+    if (str[0] == '\0' || str == endptr) {
+        return JIM_ERR;
+    }
+
+    if (endptr[0] != '\0') {
+        while (*endptr) {
+            if (!isspace(UCHAR(*endptr))) {
+                return JIM_ERR;
+            }
+            endptr++;
+        }
+    }
+    return JIM_OK;
+}
+
+static int JimNumberBase(const char *str, int *base, int *sign)
+{
+    int i = 0;
+
+    *base = 10;
+
+    while (isspace(UCHAR(str[i]))) {
+        i++;
+    }
+
+    if (str[i] == '-') {
+        *sign = -1;
+        i++;
+    }
+    else {
+        if (str[i] == '+') {
+            i++;
+        }
+        *sign = 1;
+    }
+
+    if (str[i] != '0') {
+        
+        return 0;
+    }
+
+    
+    switch (str[i + 1]) {
+        case 'x': case 'X': *base = 16; break;
+        case 'o': case 'O': *base = 8; break;
+        case 'b': case 'B': *base = 2; break;
+        default: return 0;
+    }
+    i += 2;
+    
+    if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
+        
+        return i;
+    }
+    
+    *base = 10;
+    return 0;
+}
+
+static long jim_strtol(const char *str, char **endptr)
+{
+    int sign;
+    int base;
+    int i = JimNumberBase(str, &base, &sign);
+
+    if (base != 10) {
+        long value = strtol(str + i, endptr, base);
+        if (endptr == NULL || *endptr != str + i) {
+            return value * sign;
+        }
+    }
+
+    
+    return strtol(str, endptr, 10);
+}
+
+
+static jim_wide jim_strtoull(const char *str, char **endptr)
+{
+#ifdef HAVE_LONG_LONG
+    int sign;
+    int base;
+    int i = JimNumberBase(str, &base, &sign);
+
+    if (base != 10) {
+        jim_wide value = strtoull(str + i, endptr, base);
+        if (endptr == NULL || *endptr != str + i) {
+            return value * sign;
+        }
+    }
+
+    
+    return strtoull(str, endptr, 10);
+#else
+    return (unsigned long)jim_strtol(str, endptr);
+#endif
+}
+
+int Jim_StringToWide(const char *str, jim_wide * widePtr, int base)
+{
+    char *endptr;
+
+    if (base) {
+        *widePtr = strtoull(str, &endptr, base);
+    }
+    else {
+        *widePtr = jim_strtoull(str, &endptr);
+    }
+
+    return JimCheckConversion(str, endptr);
+}
+
+int Jim_DoubleToString(char *buf, double doubleValue)
+{
+    int len;
+    int i;
+
+    len = sprintf(buf, "%.12g", doubleValue);
+
+    
+    for (i = 0; i < len; i++) {
+        if (buf[i] == '.' || buf[i] == 'e') {
+#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
+            char *e = strchr(buf, 'e');
+            if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
+                
+                e += 2;
+                memmove(e, e + 1, len - (e - buf));
+                return len - 1;
+            }
+#endif
+            return len;
+        }
+        
+        if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
+            buf[i] = toupper(UCHAR(buf[i]));
+            if (buf[i] == 'n' || buf[i] == 'N')
+                buf[i+2] = toupper(UCHAR(buf[i+2]));
+            buf[i + 3] = 0;
+            return i + 3;
+        }
+    }
+
+    buf[i++] = '.';
+    buf[i++] = '0';
+    buf[i] = '\0';
+
+    return i;
+}
+
+int Jim_StringToDouble(const char *str, double *doublePtr)
+{
+    char *endptr;
+
+    
+    errno = 0;
+
+    *doublePtr = strtod(str, &endptr);
+
+    return JimCheckConversion(str, endptr);
+}
+
+static jim_wide JimPowWide(jim_wide b, jim_wide e)
+{
+    jim_wide i, res = 1;
+
+    if ((b == 0 && e != 0) || (e < 0))
+        return 0;
+    for (i = 0; i < e; i++) {
+        res *= b;
+    }
+    return res;
+}
+
+#ifdef JIM_DEBUG_PANIC
+void JimPanicDump(int condition, const char *fmt, ...)
+{
+    va_list ap;
+
+    if (!condition) {
+        return;
+    }
+
+    va_start(ap, fmt);
+
+    fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, JIM_NL JIM_NL);
+    va_end(ap);
+
+#ifdef HAVE_BACKTRACE
+    {
+        void *array[40];
+        int size, i;
+        char **strings;
+
+        size = backtrace(array, 40);
+        strings = backtrace_symbols(array, size);
+        for (i = 0; i < size; i++)
+            fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
+        fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
+        fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
+    }
+#endif
+
+    exit(1);
+}
+#endif
+
+
+void *Jim_Alloc(int size)
+{
+    return size ? malloc(size) : NULL;
+}
+
+void Jim_Free(void *ptr)
+{
+    free(ptr);
+}
+
+void *Jim_Realloc(void *ptr, int size)
+{
+    return realloc(ptr, size);
+}
+
+char *Jim_StrDup(const char *s)
+{
+    return strdup(s);
+}
+
+char *Jim_StrDupLen(const char *s, int l)
+{
+    char *copy = Jim_Alloc(l + 1);
+
+    memcpy(copy, s, l + 1);
+    copy[l] = 0;                
+    return copy;
+}
+
+
+
+static jim_wide JimClock(void)
+{
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+
+
+static void JimExpandHashTableIfNeeded(Jim_HashTable *ht);
+static unsigned int JimHashTableNextPower(unsigned int size);
+static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace);
+
+
+
+
+unsigned int Jim_IntHashFunction(unsigned int key)
+{
+    key += ~(key << 15);
+    key ^= (key >> 10);
+    key += (key << 3);
+    key ^= (key >> 6);
+    key += ~(key << 11);
+    key ^= (key >> 16);
+    return key;
+}
+
+unsigned int Jim_GenHashFunction(const unsigned char *buf, int len)
+{
+    unsigned int h = 0;
+
+    while (len--)
+        h += (h << 3) + *buf++;
+    return h;
+}
+
+
+
+static void JimResetHashTable(Jim_HashTable *ht)
+{
+    ht->table = NULL;
+    ht->size = 0;
+    ht->sizemask = 0;
+    ht->used = 0;
+    ht->collisions = 0;
+}
+
+static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
+{
+    iter->ht = ht;
+    iter->index = -1;
+    iter->entry = NULL;
+    iter->nextEntry = NULL;
+}
+
+
+int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
+{
+    JimResetHashTable(ht);
+    ht->type = type;
+    ht->privdata = privDataPtr;
+    return JIM_OK;
+}
+
+void Jim_ResizeHashTable(Jim_HashTable *ht)
+{
+    int minimal = ht->used;
+
+    if (minimal < JIM_HT_INITIAL_SIZE)
+        minimal = JIM_HT_INITIAL_SIZE;
+    Jim_ExpandHashTable(ht, minimal);
+}
+
+
+void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
+{
+    Jim_HashTable n;            
+    unsigned int realsize = JimHashTableNextPower(size), i;
+
+     if (size <= ht->used)
+        return;
+
+    Jim_InitHashTable(&n, ht->type, ht->privdata);
+    n.size = realsize;
+    n.sizemask = realsize - 1;
+    n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
+
+    
+    memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
+
+    n.used = ht->used;
+    for (i = 0; ht->used > 0; i++) {
+        Jim_HashEntry *he, *nextHe;
+
+        if (ht->table[i] == NULL)
+            continue;
+
+        
+        he = ht->table[i];
+        while (he) {
+            unsigned int h;
+
+            nextHe = he->next;
+            
+            h = Jim_HashKey(ht, he->key) & n.sizemask;
+            he->next = n.table[h];
+            n.table[h] = he;
+            ht->used--;
+            
+            he = nextHe;
+        }
+    }
+    assert(ht->used == 0);
+    Jim_Free(ht->table);
+
+    
+    *ht = n;
+}
+
+
+int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
+{
+    Jim_HashEntry *entry;
+
+    entry = JimInsertHashEntry(ht, key, 0);
+    if (entry == NULL)
+        return JIM_ERR;
+
+    
+    Jim_SetHashKey(ht, entry, key);
+    Jim_SetHashVal(ht, entry, val);
+    return JIM_OK;
+}
+
+
+int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val)
+{
+    int existed;
+    Jim_HashEntry *entry;
+
+    entry = JimInsertHashEntry(ht, key, 1);
+    if (entry->key) {
+        
+        Jim_FreeEntryVal(ht, entry);
+        existed = 1;
+    }
+    else {
+        
+        Jim_SetHashKey(ht, entry, key);
+        existed = 0;
+    }
+    Jim_SetHashVal(ht, entry, val);
+
+    return existed;
+}
+
+
+int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
+{
+    unsigned int h;
+    Jim_HashEntry *he, *prevHe;
+
+    if (ht->used == 0)
+        return JIM_ERR;
+    h = Jim_HashKey(ht, key) & ht->sizemask;
+    he = ht->table[h];
+
+    prevHe = NULL;
+    while (he) {
+        if (Jim_CompareHashKeys(ht, key, he->key)) {
+            
+            if (prevHe)
+                prevHe->next = he->next;
+            else
+                ht->table[h] = he->next;
+            Jim_FreeEntryKey(ht, he);
+            Jim_FreeEntryVal(ht, he);
+            Jim_Free(he);
+            ht->used--;
+            return JIM_OK;
+        }
+        prevHe = he;
+        he = he->next;
+    }
+    return JIM_ERR;             
+}
+
+
+int Jim_FreeHashTable(Jim_HashTable *ht)
+{
+    unsigned int i;
+
+    
+    for (i = 0; ht->used > 0; i++) {
+        Jim_HashEntry *he, *nextHe;
+
+        if ((he = ht->table[i]) == NULL)
+            continue;
+        while (he) {
+            nextHe = he->next;
+            Jim_FreeEntryKey(ht, he);
+            Jim_FreeEntryVal(ht, he);
+            Jim_Free(he);
+            ht->used--;
+            he = nextHe;
+        }
+    }
+    
+    Jim_Free(ht->table);
+    
+    JimResetHashTable(ht);
+    return JIM_OK;              
+}
+
+Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
+{
+    Jim_HashEntry *he;
+    unsigned int h;
+
+    if (ht->used == 0)
+        return NULL;
+    h = Jim_HashKey(ht, key) & ht->sizemask;
+    he = ht->table[h];
+    while (he) {
+        if (Jim_CompareHashKeys(ht, key, he->key))
+            return he;
+        he = he->next;
+    }
+    return NULL;
+}
+
+Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
+{
+    Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
+    JimInitHashTableIterator(ht, iter);
+    return iter;
+}
+
+Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
+{
+    while (1) {
+        if (iter->entry == NULL) {
+            iter->index++;
+            if (iter->index >= (signed)iter->ht->size)
+                break;
+            iter->entry = iter->ht->table[iter->index];
+        }
+        else {
+            iter->entry = iter->nextEntry;
+        }
+        if (iter->entry) {
+            iter->nextEntry = iter->entry->next;
+            return iter->entry;
+        }
+    }
+    return NULL;
+}
+
+
+
+
+static void JimExpandHashTableIfNeeded(Jim_HashTable *ht)
+{
+    if (ht->size == 0)
+        Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE);
+    if (ht->size == ht->used)
+        Jim_ExpandHashTable(ht, ht->size * 2);
+}
+
+
+static unsigned int JimHashTableNextPower(unsigned int size)
+{
+    unsigned int i = JIM_HT_INITIAL_SIZE;
+
+    if (size >= 2147483648U)
+        return 2147483648U;
+    while (1) {
+        if (i >= size)
+            return i;
+        i *= 2;
+    }
+}
+
+static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
+{
+    unsigned int h;
+    Jim_HashEntry *he;
+
+    
+    JimExpandHashTableIfNeeded(ht);
+
+    
+    h = Jim_HashKey(ht, key) & ht->sizemask;
+    
+    he = ht->table[h];
+    while (he) {
+        if (Jim_CompareHashKeys(ht, key, he->key))
+            return replace ? he : NULL;
+        he = he->next;
+    }
+
+    
+    he = Jim_Alloc(sizeof(*he));
+    he->next = ht->table[h];
+    ht->table[h] = he;
+    ht->used++;
+    he->key = NULL;
+
+    return he;
+}
+
+
+
+static unsigned int JimStringCopyHTHashFunction(const void *key)
+{
+    return Jim_GenHashFunction(key, strlen(key));
+}
+
+static void *JimStringCopyHTDup(void *privdata, const void *key)
+{
+    return strdup(key);
+}
+
+static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
+{
+    return strcmp(key1, key2) == 0;
+}
+
+static void JimStringCopyHTKeyDestructor(void *privdata, void *key)
+{
+    Jim_Free(key);
+}
+
+static const Jim_HashTableType JimPackageHashTableType = {
+    JimStringCopyHTHashFunction,     
+    JimStringCopyHTDup,              
+    NULL,                            
+    JimStringCopyHTKeyCompare,       
+    JimStringCopyHTKeyDestructor,    
+    NULL                             
+};
+
+typedef struct AssocDataValue
+{
+    Jim_InterpDeleteProc *delProc;
+    void *data;
+} AssocDataValue;
+
+static void JimAssocDataHashTableValueDestructor(void *privdata, void *data)
+{
+    AssocDataValue *assocPtr = (AssocDataValue *) data;
+
+    if (assocPtr->delProc != NULL)
+        assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
+    Jim_Free(data);
+}
+
+static const Jim_HashTableType JimAssocDataHashTableType = {
+    JimStringCopyHTHashFunction,    
+    JimStringCopyHTDup,             
+    NULL,                           
+    JimStringCopyHTKeyCompare,      
+    JimStringCopyHTKeyDestructor,   
+    JimAssocDataHashTableValueDestructor        
+};
+
+void Jim_InitStack(Jim_Stack *stack)
+{
+    stack->len = 0;
+    stack->maxlen = 0;
+    stack->vector = NULL;
+}
+
+void Jim_FreeStack(Jim_Stack *stack)
+{
+    Jim_Free(stack->vector);
+}
+
+int Jim_StackLen(Jim_Stack *stack)
+{
+    return stack->len;
+}
+
+void Jim_StackPush(Jim_Stack *stack, void *element)
+{
+    int neededLen = stack->len + 1;
+
+    if (neededLen > stack->maxlen) {
+        stack->maxlen = neededLen < 20 ? 20 : neededLen * 2;
+        stack->vector = Jim_Realloc(stack->vector, sizeof(void *) * stack->maxlen);
+    }
+    stack->vector[stack->len] = element;
+    stack->len++;
+}
+
+void *Jim_StackPop(Jim_Stack *stack)
+{
+    if (stack->len == 0)
+        return NULL;
+    stack->len--;
+    return stack->vector[stack->len];
+}
+
+void *Jim_StackPeek(Jim_Stack *stack)
+{
+    if (stack->len == 0)
+        return NULL;
+    return stack->vector[stack->len - 1];
+}
+
+void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr))
+{
+    int i;
+
+    for (i = 0; i < stack->len; i++)
+        freeFunc(stack->vector[i]);
+}
+
+
+
+#define JIM_TT_NONE    0           
+#define JIM_TT_STR     1          
+#define JIM_TT_ESC     2          
+#define JIM_TT_VAR     3          
+#define JIM_TT_DICTSUGAR   4      
+#define JIM_TT_CMD     5          
+
+#define JIM_TT_SEP     6          
+#define JIM_TT_EOL     7          
+#define JIM_TT_EOF     8          
+
+#define JIM_TT_LINE    9          
+#define JIM_TT_WORD   10          
+
+
+#define JIM_TT_SUBEXPR_START  11
+#define JIM_TT_SUBEXPR_END    12
+#define JIM_TT_SUBEXPR_COMMA  13
+#define JIM_TT_EXPR_INT       14
+#define JIM_TT_EXPR_DOUBLE    15
+
+#define JIM_TT_EXPRSUGAR      16  
+
+
+#define JIM_TT_EXPR_OP        20
+
+#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
+
+
+#define JIM_PS_DEF 0            
+#define JIM_PS_QUOTE 1          
+#define JIM_PS_DICTSUGAR 2      
+
+struct JimParserCtx
+{
+    const char *p;              
+    int len;                    
+    int linenr;                 
+    const char *tstart;
+    const char *tend;           
+    int tline;                  
+    int tt;                     
+    int eof;                    
+    int state;                  
+    int comment;                
+    char missing;               
+    int missingline;            
+};
+
+struct JimParseResult {
+    char missing;               
+    int line;                   
+};
+
+static int JimParseScript(struct JimParserCtx *pc);
+static int JimParseSep(struct JimParserCtx *pc);
+static int JimParseEol(struct JimParserCtx *pc);
+static int JimParseCmd(struct JimParserCtx *pc);
+static int JimParseQuote(struct JimParserCtx *pc);
+static int JimParseVar(struct JimParserCtx *pc);
+static int JimParseBrace(struct JimParserCtx *pc);
+static int JimParseStr(struct JimParserCtx *pc);
+static int JimParseComment(struct JimParserCtx *pc);
+static void JimParseSubCmd(struct JimParserCtx *pc);
+static int JimParseSubQuote(struct JimParserCtx *pc);
+static void JimParseSubCmd(struct JimParserCtx *pc);
+static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
+
+static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr)
+{
+    pc->p = prg;
+    pc->len = len;
+    pc->tstart = NULL;
+    pc->tend = NULL;
+    pc->tline = 0;
+    pc->tt = JIM_TT_NONE;
+    pc->eof = 0;
+    pc->state = JIM_PS_DEF;
+    pc->linenr = linenr;
+    pc->comment = 1;
+    pc->missing = ' ';
+    pc->missingline = linenr;
+}
+
+static int JimParseScript(struct JimParserCtx *pc)
+{
+    while (1) {                 
+        if (!pc->len) {
+            pc->tstart = pc->p;
+            pc->tend = pc->p - 1;
+            pc->tline = pc->linenr;
+            pc->tt = JIM_TT_EOL;
+            pc->eof = 1;
+            return JIM_OK;
+        }
+        switch (*(pc->p)) {
+            case '\\':
+                if (*(pc->p + 1) == '\n' && pc->state == JIM_PS_DEF) {
+                    return JimParseSep(pc);
+                }
+                pc->comment = 0;
+                return JimParseStr(pc);
+            case ' ':
+            case '\t':
+            case '\r':
+            case '\f':
+                if (pc->state == JIM_PS_DEF)
+                    return JimParseSep(pc);
+                pc->comment = 0;
+                return JimParseStr(pc);
+            case '\n':
+            case ';':
+                pc->comment = 1;
+                if (pc->state == JIM_PS_DEF)
+                    return JimParseEol(pc);
+                return JimParseStr(pc);
+            case '[':
+                pc->comment = 0;
+                return JimParseCmd(pc);
+            case '$':
+                pc->comment = 0;
+                if (JimParseVar(pc) == JIM_ERR) {
+                    
+                    pc->tstart = pc->tend = pc->p++;
+                    pc->len--;
+                    pc->tt = JIM_TT_ESC;
+                }
+                return JIM_OK;
+            case '#':
+                if (pc->comment) {
+                    JimParseComment(pc);
+                    continue;
+                }
+                return JimParseStr(pc);
+            default:
+                pc->comment = 0;
+                return JimParseStr(pc);
+        }
+        return JIM_OK;
+    }
+}
+
+static int JimParseSep(struct JimParserCtx *pc)
+{
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+    while (isspace(UCHAR(*pc->p)) || (*pc->p == '\\' && *(pc->p + 1) == '\n')) {
+        if (*pc->p == '\n') {
+            break;
+        }
+        if (*pc->p == '\\') {
+            pc->p++;
+            pc->len--;
+            pc->linenr++;
+        }
+        pc->p++;
+        pc->len--;
+    }
+    pc->tend = pc->p - 1;
+    pc->tt = JIM_TT_SEP;
+    return JIM_OK;
+}
+
+static int JimParseEol(struct JimParserCtx *pc)
+{
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+    while (isspace(UCHAR(*pc->p)) || *pc->p == ';') {
+        if (*pc->p == '\n')
+            pc->linenr++;
+        pc->p++;
+        pc->len--;
+    }
+    pc->tend = pc->p - 1;
+    pc->tt = JIM_TT_EOL;
+    return JIM_OK;
+}
+
+
+static void JimParseSubBrace(struct JimParserCtx *pc)
+{
+    int level = 1;
+
+    
+    pc->p++;
+    pc->len--;
+    while (pc->len) {
+        switch (*pc->p) {
+            case '\\':
+                if (pc->len > 1) {
+                    if (*++pc->p == '\n') {
+                        pc->linenr++;
+                    }
+                    pc->len--;
+                }
+                break;
+
+            case '{':
+                level++;
+                break;
+
+            case '}':
+                if (--level == 0) {
+                    pc->tend = pc->p - 1;
+                    pc->p++;
+                    pc->len--;
+                    return;
+                }
+                break;
+
+            case '\n':
+                pc->linenr++;
+                break;
+        }
+        pc->p++;
+        pc->len--;
+    }
+    pc->missing = '{';
+    pc->missingline = pc->tline;
+    pc->tend = pc->p - 1;
+}
+
+static int JimParseSubQuote(struct JimParserCtx *pc)
+{
+    int tt = JIM_TT_STR;
+    int line = pc->tline;
+
+    
+    pc->p++;
+    pc->len--;
+    while (pc->len) {
+        switch (*pc->p) {
+            case '\\':
+                if (pc->len > 1) {
+                    if (*++pc->p == '\n') {
+                        pc->linenr++;
+                    }
+                    pc->len--;
+                    tt = JIM_TT_ESC;
+                }
+                break;
+
+            case '"':
+                pc->tend = pc->p - 1;
+                pc->p++;
+                pc->len--;
+                return tt;
+
+            case '[':
+                JimParseSubCmd(pc);
+                tt = JIM_TT_ESC;
+                continue;
+
+            case '\n':
+                pc->linenr++;
+                break;
+
+            case '$':
+                tt = JIM_TT_ESC;
+                break;
+        }
+        pc->p++;
+        pc->len--;
+    }
+    pc->missing = '"';
+    pc->missingline = line;
+    pc->tend = pc->p - 1;
+    return tt;
+}
+
+static void JimParseSubCmd(struct JimParserCtx *pc)
+{
+    int level = 1;
+    int startofword = 1;
+    int line = pc->tline;
+
+    
+    pc->p++;
+    pc->len--;
+    while (pc->len) {
+        switch (*pc->p) {
+            case '\\':
+                if (pc->len > 1) {
+                    if (*++pc->p == '\n') {
+                        pc->linenr++;
+                    }
+                    pc->len--;
+                }
+                break;
+
+            case '[':
+                level++;
+                break;
+
+            case ']':
+                if (--level == 0) {
+                    pc->tend = pc->p - 1;
+                    pc->p++;
+                    pc->len--;
+                    return;
+                }
+                break;
+
+            case '"':
+                if (startofword) {
+                    JimParseSubQuote(pc);
+                    continue;
+                }
+                break;
+
+            case '{':
+                JimParseSubBrace(pc);
+                startofword = 0;
+                continue;
+
+            case '\n':
+                pc->linenr++;
+                break;
+        }
+        startofword = isspace(UCHAR(*pc->p));
+        pc->p++;
+        pc->len--;
+    }
+    pc->missing = '[';
+    pc->missingline = line;
+    pc->tend = pc->p - 1;
+}
+
+static int JimParseBrace(struct JimParserCtx *pc)
+{
+    pc->tstart = pc->p + 1;
+    pc->tline = pc->linenr;
+    pc->tt = JIM_TT_STR;
+    JimParseSubBrace(pc);
+    return JIM_OK;
+}
+
+static int JimParseCmd(struct JimParserCtx *pc)
+{
+    pc->tstart = pc->p + 1;
+    pc->tline = pc->linenr;
+    pc->tt = JIM_TT_CMD;
+    JimParseSubCmd(pc);
+    return JIM_OK;
+}
+
+static int JimParseQuote(struct JimParserCtx *pc)
+{
+    pc->tstart = pc->p + 1;
+    pc->tline = pc->linenr;
+    pc->tt = JimParseSubQuote(pc);
+    return JIM_OK;
+}
+
+static int JimParseVar(struct JimParserCtx *pc)
+{
+    
+    pc->p++;
+    pc->len--;
+
+#ifdef EXPRSUGAR_BRACKET
+    if (*pc->p == '[') {
+        
+        JimParseCmd(pc);
+        pc->tt = JIM_TT_EXPRSUGAR;
+        return JIM_OK;
+    }
+#endif
+
+    pc->tstart = pc->p;
+    pc->tt = JIM_TT_VAR;
+    pc->tline = pc->linenr;
+
+    if (*pc->p == '{') {
+        pc->tstart = ++pc->p;
+        pc->len--;
+
+        while (pc->len && *pc->p != '}') {
+            if (*pc->p == '\n') {
+                pc->linenr++;
+            }
+            pc->p++;
+            pc->len--;
+        }
+        pc->tend = pc->p - 1;
+        if (pc->len) {
+            pc->p++;
+            pc->len--;
+        }
+    }
+    else {
+        while (1) {
+            
+            if (pc->p[0] == ':' && pc->p[1] == ':') {
+                while (*pc->p == ':') {
+                    pc->p++;
+                    pc->len--;
+                }
+                continue;
+            }
+            if (isalnum(UCHAR(*pc->p)) || *pc->p == '_' || UCHAR(*pc->p) >= 0x80) {
+                pc->p++;
+                pc->len--;
+                continue;
+            }
+            break;
+        }
+        
+        if (*pc->p == '(') {
+            int count = 1;
+            const char *paren = NULL;
+
+            pc->tt = JIM_TT_DICTSUGAR;
+
+            while (count && pc->len) {
+                pc->p++;
+                pc->len--;
+                if (*pc->p == '\\' && pc->len >= 1) {
+                    pc->p++;
+                    pc->len--;
+                }
+                else if (*pc->p == '(') {
+                    count++;
+                }
+                else if (*pc->p == ')') {
+                    paren = pc->p;
+                    count--;
+                }
+            }
+            if (count == 0) {
+                pc->p++;
+                pc->len--;
+            }
+            else if (paren) {
+                
+                paren++;
+                pc->len += (pc->p - paren);
+                pc->p = paren;
+            }
+#ifndef EXPRSUGAR_BRACKET
+            if (*pc->tstart == '(') {
+                pc->tt = JIM_TT_EXPRSUGAR;
+            }
+#endif
+        }
+        pc->tend = pc->p - 1;
+    }
+    if (pc->tstart == pc->p) {
+        pc->p--;
+        pc->len++;
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int JimParseStr(struct JimParserCtx *pc)
+{
+    if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
+        pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
+        
+        if (*pc->p == '{') {
+            return JimParseBrace(pc);
+        }
+        if (*pc->p == '"') {
+            pc->state = JIM_PS_QUOTE;
+            pc->p++;
+            pc->len--;
+            
+            pc->missingline = pc->tline;
+        }
+    }
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+    while (1) {
+        if (pc->len == 0) {
+            if (pc->state == JIM_PS_QUOTE) {
+                pc->missing = '"';
+            }
+            pc->tend = pc->p - 1;
+            pc->tt = JIM_TT_ESC;
+            return JIM_OK;
+        }
+        switch (*pc->p) {
+            case '\\':
+                if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') {
+                    pc->tend = pc->p - 1;
+                    pc->tt = JIM_TT_ESC;
+                    return JIM_OK;
+                }
+                if (pc->len >= 2) {
+                    if (*(pc->p + 1) == '\n') {
+                        pc->linenr++;
+                    }
+                    pc->p++;
+                    pc->len--;
+                }
+                break;
+            case '(':
+                
+                if (pc->len > 1 && pc->p[1] != '$') {
+                    break;
+                }
+            case ')':
+                
+                if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
+                    if (pc->p == pc->tstart) {
+                        
+                        pc->p++;
+                        pc->len--;
+                    }
+                    pc->tend = pc->p - 1;
+                    pc->tt = JIM_TT_ESC;
+                    return JIM_OK;
+                }
+                break;
+
+            case '$':
+            case '[':
+                pc->tend = pc->p - 1;
+                pc->tt = JIM_TT_ESC;
+                return JIM_OK;
+            case ' ':
+            case '\t':
+            case '\n':
+            case '\r':
+            case '\f':
+            case ';':
+                if (pc->state == JIM_PS_DEF) {
+                    pc->tend = pc->p - 1;
+                    pc->tt = JIM_TT_ESC;
+                    return JIM_OK;
+                }
+                else if (*pc->p == '\n') {
+                    pc->linenr++;
+                }
+                break;
+            case '"':
+                if (pc->state == JIM_PS_QUOTE) {
+                    pc->tend = pc->p - 1;
+                    pc->tt = JIM_TT_ESC;
+                    pc->p++;
+                    pc->len--;
+                    pc->state = JIM_PS_DEF;
+                    return JIM_OK;
+                }
+                break;
+        }
+        pc->p++;
+        pc->len--;
+    }
+    return JIM_OK;              
+}
+
+static int JimParseComment(struct JimParserCtx *pc)
+{
+    while (*pc->p) {
+        if (*pc->p == '\n') {
+            pc->linenr++;
+            if (*(pc->p - 1) != '\\') {
+                pc->p++;
+                pc->len--;
+                return JIM_OK;
+            }
+        }
+        pc->p++;
+        pc->len--;
+    }
+    return JIM_OK;
+}
+
+
+static int xdigitval(int c)
+{
+    if (c >= '0' && c <= '9')
+        return c - '0';
+    if (c >= 'a' && c <= 'f')
+        return c - 'a' + 10;
+    if (c >= 'A' && c <= 'F')
+        return c - 'A' + 10;
+    return -1;
+}
+
+static int odigitval(int c)
+{
+    if (c >= '0' && c <= '7')
+        return c - '0';
+    return -1;
+}
+
+static int JimEscape(char *dest, const char *s, int slen)
+{
+    char *p = dest;
+    int i, len;
+
+    if (slen == -1)
+        slen = strlen(s);
+
+    for (i = 0; i < slen; i++) {
+        switch (s[i]) {
+            case '\\':
+                switch (s[i + 1]) {
+                    case 'a':
+                        *p++ = 0x7;
+                        i++;
+                        break;
+                    case 'b':
+                        *p++ = 0x8;
+                        i++;
+                        break;
+                    case 'f':
+                        *p++ = 0xc;
+                        i++;
+                        break;
+                    case 'n':
+                        *p++ = 0xa;
+                        i++;
+                        break;
+                    case 'r':
+                        *p++ = 0xd;
+                        i++;
+                        break;
+                    case 't':
+                        *p++ = 0x9;
+                        i++;
+                        break;
+                    case 'u':
+                    case 'U':
+                    case 'x':
+                        {
+                            unsigned val = 0;
+                            int k;
+                            int maxchars = 2;
+
+                            i++;
+
+                            if (s[i] == 'U') {
+                                maxchars = 8;
+                            }
+                            else if (s[i] == 'u') {
+                                if (s[i + 1] == '{') {
+                                    maxchars = 6;
+                                    i++;
+                                }
+                                else {
+                                    maxchars = 4;
+                                }
+                            }
+
+                            for (k = 0; k < maxchars; k++) {
+                                int c = xdigitval(s[i + k + 1]);
+                                if (c == -1) {
+                                    break;
+                                }
+                                val = (val << 4) | c;
+                            }
+                            
+                            if (s[i] == '{') {
+                                if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
+                                    
+                                    i--;
+                                    k = 0;
+                                }
+                                else {
+                                    
+                                    k++;
+                                }
+                            }
+                            if (k) {
+                                
+                                if (s[i] == 'x') {
+                                    *p++ = val;
+                                }
+                                else {
+                                    p += utf8_fromunicode(p, val);
+                                }
+                                i += k;
+                                break;
+                            }
+                            
+                            *p++ = s[i];
+                        }
+                        break;
+                    case 'v':
+                        *p++ = 0xb;
+                        i++;
+                        break;
+                    case '\0':
+                        *p++ = '\\';
+                        i++;
+                        break;
+                    case '\n':
+                        
+                        *p++ = ' ';
+                        do {
+                            i++;
+                        } while (s[i + 1] == ' ' || s[i + 1] == '\t');
+                        break;
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                        
+                        {
+                            int val = 0;
+                            int c = odigitval(s[i + 1]);
+
+                            val = c;
+                            c = odigitval(s[i + 2]);
+                            if (c == -1) {
+                                *p++ = val;
+                                i++;
+                                break;
+                            }
+                            val = (val * 8) + c;
+                            c = odigitval(s[i + 3]);
+                            if (c == -1) {
+                                *p++ = val;
+                                i += 2;
+                                break;
+                            }
+                            val = (val * 8) + c;
+                            *p++ = val;
+                            i += 3;
+                        }
+                        break;
+                    default:
+                        *p++ = s[i + 1];
+                        i++;
+                        break;
+                }
+                break;
+            default:
+                *p++ = s[i];
+                break;
+        }
+    }
+    len = p - dest;
+    *p = '\0';
+    return len;
+}
+
+static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc)
+{
+    const char *start, *end;
+    char *token;
+    int len;
+
+    start = pc->tstart;
+    end = pc->tend;
+    if (start > end) {
+        len = 0;
+        token = Jim_Alloc(1);
+        token[0] = '\0';
+    }
+    else {
+        len = (end - start) + 1;
+        token = Jim_Alloc(len + 1);
+        if (pc->tt != JIM_TT_ESC) {
+            
+            memcpy(token, start, len);
+            token[len] = '\0';
+        }
+        else {
+            
+            len = JimEscape(token, start, len);
+        }
+    }
+
+    return Jim_NewStringObjNoAlloc(interp, token, len);
+}
+
+int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr)
+{
+    struct JimParserCtx parser;
+
+    JimParserInit(&parser, s, len, 1);
+    while (!parser.eof) {
+        JimParseScript(&parser);
+    }
+    if (stateCharPtr) {
+        *stateCharPtr = parser.missing;
+    }
+    return parser.missing == ' ';
+}
+
+static int JimParseListSep(struct JimParserCtx *pc);
+static int JimParseListStr(struct JimParserCtx *pc);
+static int JimParseListQuote(struct JimParserCtx *pc);
+
+static int JimParseList(struct JimParserCtx *pc)
+{
+    if (isspace(UCHAR(*pc->p))) {
+        return JimParseListSep(pc);
+    }
+    switch (*pc->p) {
+        case '"':
+            return JimParseListQuote(pc);
+
+        case '{':
+            return JimParseBrace(pc);
+
+        default:
+            if (pc->len) {
+                return JimParseListStr(pc);
+            }
+            break;
+    }
+
+    pc->tstart = pc->tend = pc->p;
+    pc->tline = pc->linenr;
+    pc->tt = JIM_TT_EOL;
+    pc->eof = 1;
+    return JIM_OK;
+}
+
+static int JimParseListSep(struct JimParserCtx *pc)
+{
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+    while (isspace(UCHAR(*pc->p))) {
+        if (*pc->p == '\n') {
+            pc->linenr++;
+        }
+        pc->p++;
+        pc->len--;
+    }
+    pc->tend = pc->p - 1;
+    pc->tt = JIM_TT_SEP;
+    return JIM_OK;
+}
+
+static int JimParseListQuote(struct JimParserCtx *pc)
+{
+    pc->p++;
+    pc->len--;
+
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+    pc->tt = JIM_TT_STR;
+
+    while (pc->len) {
+        switch (*pc->p) {
+            case '\\':
+                pc->tt = JIM_TT_ESC;
+                if (--pc->len == 0) {
+                    
+                    pc->tend = pc->p;
+                    return JIM_OK;
+                }
+                pc->p++;
+                break;
+            case '\n':
+                pc->linenr++;
+                break;
+            case '"':
+                pc->tend = pc->p - 1;
+                pc->p++;
+                pc->len--;
+                return JIM_OK;
+        }
+        pc->p++;
+        pc->len--;
+    }
+
+    pc->tend = pc->p - 1;
+    return JIM_OK;
+}
+
+static int JimParseListStr(struct JimParserCtx *pc)
+{
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+    pc->tt = JIM_TT_STR;
+
+    while (pc->len) {
+        if (isspace(UCHAR(*pc->p))) {
+            pc->tend = pc->p - 1;
+            return JIM_OK;
+        }
+        if (*pc->p == '\\') {
+            if (--pc->len == 0) {
+                
+                pc->tend = pc->p;
+                return JIM_OK;
+            }
+            pc->tt = JIM_TT_ESC;
+            pc->p++;
+        }
+        pc->p++;
+        pc->len--;
+    }
+    pc->tend = pc->p - 1;
+    return JIM_OK;
+}
+
+
+
+Jim_Obj *Jim_NewObj(Jim_Interp *interp)
+{
+    Jim_Obj *objPtr;
+
+    
+    if (interp->freeList != NULL) {
+        
+        objPtr = interp->freeList;
+        interp->freeList = objPtr->nextObjPtr;
+    }
+    else {
+        
+        objPtr = Jim_Alloc(sizeof(*objPtr));
+    }
+
+    objPtr->refCount = 0;
+
+    
+    objPtr->prevObjPtr = NULL;
+    objPtr->nextObjPtr = interp->liveList;
+    if (interp->liveList)
+        interp->liveList->prevObjPtr = objPtr;
+    interp->liveList = objPtr;
+
+    return objPtr;
+}
+
+void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    
+    JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr,
+        objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>"));
+
+    
+    Jim_FreeIntRep(interp, objPtr);
+    
+    if (objPtr->bytes != NULL) {
+        if (objPtr->bytes != JimEmptyStringRep)
+            Jim_Free(objPtr->bytes);
+    }
+    
+    if (objPtr->prevObjPtr)
+        objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
+    if (objPtr->nextObjPtr)
+        objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
+    if (interp->liveList == objPtr)
+        interp->liveList = objPtr->nextObjPtr;
+#ifdef JIM_DISABLE_OBJECT_POOL
+    Jim_Free(objPtr);
+#else
+    
+    objPtr->prevObjPtr = NULL;
+    objPtr->nextObjPtr = interp->freeList;
+    if (interp->freeList)
+        interp->freeList->prevObjPtr = objPtr;
+    interp->freeList = objPtr;
+    objPtr->refCount = -1;
+#endif
+}
+
+
+void Jim_InvalidateStringRep(Jim_Obj *objPtr)
+{
+    if (objPtr->bytes != NULL) {
+        if (objPtr->bytes != JimEmptyStringRep)
+            Jim_Free(objPtr->bytes);
+    }
+    objPtr->bytes = NULL;
+}
+
+
+Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_Obj *dupPtr;
+
+    dupPtr = Jim_NewObj(interp);
+    if (objPtr->bytes == NULL) {
+        
+        dupPtr->bytes = NULL;
+    }
+    else if (objPtr->length == 0) {
+        
+        dupPtr->bytes = JimEmptyStringRep;
+        dupPtr->length = 0;
+        dupPtr->typePtr = NULL;
+        return dupPtr;
+    }
+    else {
+        dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
+        dupPtr->length = objPtr->length;
+        
+        memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
+    }
+
+    
+    dupPtr->typePtr = objPtr->typePtr;
+    if (objPtr->typePtr != NULL) {
+        if (objPtr->typePtr->dupIntRepProc == NULL) {
+            dupPtr->internalRep = objPtr->internalRep;
+        }
+        else {
+            
+            objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
+        }
+    }
+    return dupPtr;
+}
+
+const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
+{
+    if (objPtr->bytes == NULL) {
+        
+        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+        objPtr->typePtr->updateStringProc(objPtr);
+    }
+    if (lenPtr)
+        *lenPtr = objPtr->length;
+    return objPtr->bytes;
+}
+
+
+int Jim_Length(Jim_Obj *objPtr)
+{
+    if (objPtr->bytes == NULL) {
+        
+        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+        objPtr->typePtr->updateStringProc(objPtr);
+    }
+    return objPtr->length;
+}
+
+
+const char *Jim_String(Jim_Obj *objPtr)
+{
+    if (objPtr->bytes == NULL) {
+        
+        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+        objPtr->typePtr->updateStringProc(objPtr);
+    }
+    return objPtr->bytes;
+}
+
+static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+
+static const Jim_ObjType dictSubstObjType = {
+    "dict-substitution",
+    FreeDictSubstInternalRep,
+    DupDictSubstInternalRep,
+    NULL,
+    JIM_TYPE_NONE,
+};
+
+static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
+}
+
+static const Jim_ObjType interpolatedObjType = {
+    "interpolated",
+    FreeInterpolatedInternalRep,
+    NULL,
+    NULL,
+    JIM_TYPE_NONE,
+};
+
+static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+
+static const Jim_ObjType stringObjType = {
+    "string",
+    NULL,
+    DupStringInternalRep,
+    NULL,
+    JIM_TYPE_REFERENCES,
+};
+
+static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    JIM_NOTUSED(interp);
+
+    dupPtr->internalRep.strValue.maxLength = srcPtr->length;
+
+    dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
+}
+
+static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    if (objPtr->typePtr != &stringObjType) {
+        
+        if (objPtr->bytes == NULL) {
+            
+            JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+            objPtr->typePtr->updateStringProc(objPtr);
+        }
+        
+        Jim_FreeIntRep(interp, objPtr);
+        
+        objPtr->typePtr = &stringObjType;
+        objPtr->internalRep.strValue.maxLength = objPtr->length;
+        
+        objPtr->internalRep.strValue.charLength = -1;
+    }
+    return JIM_OK;
+}
+
+int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+#ifdef JIM_UTF8
+    SetStringFromAny(interp, objPtr);
+
+    if (objPtr->internalRep.strValue.charLength < 0) {
+        objPtr->internalRep.strValue.charLength = utf8_strlen(objPtr->bytes, objPtr->length);
+    }
+    return objPtr->internalRep.strValue.charLength;
+#else
+    return Jim_Length(objPtr);
+#endif
+}
+
+
+Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
+{
+    Jim_Obj *objPtr = Jim_NewObj(interp);
+
+    
+    if (len == -1)
+        len = strlen(s);
+    
+    if (len == 0) {
+        objPtr->bytes = JimEmptyStringRep;
+        objPtr->length = 0;
+    }
+    else {
+        objPtr->bytes = Jim_Alloc(len + 1);
+        objPtr->length = len;
+        memcpy(objPtr->bytes, s, len);
+        objPtr->bytes[len] = '\0';
+    }
+
+    
+    objPtr->typePtr = NULL;
+    return objPtr;
+}
+
+
+Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen)
+{
+#ifdef JIM_UTF8
+    
+    int bytelen = utf8_index(s, charlen);
+
+    Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen);
+
+    
+    objPtr->typePtr = &stringObjType;
+    objPtr->internalRep.strValue.maxLength = bytelen;
+    objPtr->internalRep.strValue.charLength = charlen;
+
+    return objPtr;
+#else
+    return Jim_NewStringObj(interp, s, charlen);
+#endif
+}
+
+Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
+{
+    Jim_Obj *objPtr = Jim_NewObj(interp);
+
+    objPtr->bytes = s;
+    objPtr->length = len == -1 ? strlen(s) : len;
+    objPtr->typePtr = NULL;
+    return objPtr;
+}
+
+static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
+{
+    int needlen;
+
+    if (len == -1)
+        len = strlen(str);
+    needlen = objPtr->length + len;
+    if (objPtr->internalRep.strValue.maxLength < needlen ||
+        objPtr->internalRep.strValue.maxLength == 0) {
+        needlen *= 2;
+        
+        if (needlen < 7) {
+            needlen = 7;
+        }
+        if (objPtr->bytes == JimEmptyStringRep) {
+            objPtr->bytes = Jim_Alloc(needlen + 1);
+        }
+        else {
+            objPtr->bytes = Jim_Realloc(objPtr->bytes, needlen + 1);
+        }
+        objPtr->internalRep.strValue.maxLength = needlen;
+    }
+    memcpy(objPtr->bytes + objPtr->length, str, len);
+    objPtr->bytes[objPtr->length + len] = '\0';
+    if (objPtr->internalRep.strValue.charLength >= 0) {
+        
+        objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
+    }
+    objPtr->length += len;
+}
+
+
+void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
+{
+    JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
+    SetStringFromAny(interp, objPtr);
+    StringAppendString(objPtr, str, len);
+}
+
+void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
+{
+    int len;
+    const char *str;
+
+    str = Jim_GetString(appendObjPtr, &len);
+    Jim_AppendString(interp, objPtr, str, len);
+}
+
+void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
+{
+    va_list ap;
+
+    SetStringFromAny(interp, objPtr);
+    va_start(ap, objPtr);
+    while (1) {
+        char *s = va_arg(ap, char *);
+
+        if (s == NULL)
+            break;
+        Jim_AppendString(interp, objPtr, s, -1);
+    }
+    va_end(ap);
+}
+
+int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
+{
+    const char *aStr, *bStr;
+    int aLen, bLen;
+
+    if (aObjPtr == bObjPtr)
+        return 1;
+    aStr = Jim_GetString(aObjPtr, &aLen);
+    bStr = Jim_GetString(bObjPtr, &bLen);
+    if (aLen != bLen)
+        return 0;
+    return JimStringCompare(aStr, aLen, bStr, bLen) == 0;
+}
+
+int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
+{
+    return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
+}
+
+int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase)
+{
+    int l1, l2;
+    const char *s1 = Jim_GetString(firstObjPtr, &l1);
+    const char *s2 = Jim_GetString(secondObjPtr, &l2);
+
+    if (nocase) {
+        
+        return JimStringCompareLen(s1, s2, -1, nocase);
+    }
+    return JimStringCompare(s1, l1, s2, l2);
+}
+
+int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase)
+{
+    const char *s1 = Jim_String(firstObjPtr);
+    const char *s2 = Jim_String(secondObjPtr);
+
+    return JimStringCompareLen(s1, s2, Jim_Utf8Length(interp, firstObjPtr), nocase);
+}
+
+static int JimRelToAbsIndex(int len, int idx)
+{
+    if (idx < 0)
+        return len + idx;
+    return idx;
+}
+
+static void JimRelToAbsRange(int len, int *firstPtr, int *lastPtr, int *rangeLenPtr)
+{
+    int rangeLen;
+
+    if (*firstPtr > *lastPtr) {
+        rangeLen = 0;
+    }
+    else {
+        rangeLen = *lastPtr - *firstPtr + 1;
+        if (rangeLen) {
+            if (*firstPtr < 0) {
+                rangeLen += *firstPtr;
+                *firstPtr = 0;
+            }
+            if (*lastPtr >= len) {
+                rangeLen -= (*lastPtr - (len - 1));
+                *lastPtr = len - 1;
+            }
+        }
+    }
+    if (rangeLen < 0)
+        rangeLen = 0;
+
+    *rangeLenPtr = rangeLen;
+}
+
+static int JimStringGetRange(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr,
+    int len, int *first, int *last, int *range)
+{
+    if (Jim_GetIndex(interp, firstObjPtr, first) != JIM_OK) {
+        return JIM_ERR;
+    }
+    if (Jim_GetIndex(interp, lastObjPtr, last) != JIM_OK) {
+        return JIM_ERR;
+    }
+    *first = JimRelToAbsIndex(len, *first);
+    *last = JimRelToAbsIndex(len, *last);
+    JimRelToAbsRange(len, first, last, range);
+    return JIM_OK;
+}
+
+Jim_Obj *Jim_StringByteRangeObj(Jim_Interp *interp,
+    Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr)
+{
+    int first, last;
+    const char *str;
+    int rangeLen;
+    int bytelen;
+
+    str = Jim_GetString(strObjPtr, &bytelen);
+
+    if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, bytelen, &first, &last, &rangeLen) != JIM_OK) {
+        return NULL;
+    }
+
+    if (first == 0 && rangeLen == bytelen) {
+        return strObjPtr;
+    }
+    return Jim_NewStringObj(interp, str + first, rangeLen);
+}
+
+Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp,
+    Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr)
+{
+#ifdef JIM_UTF8
+    int first, last;
+    const char *str;
+    int len, rangeLen;
+    int bytelen;
+
+    str = Jim_GetString(strObjPtr, &bytelen);
+    len = Jim_Utf8Length(interp, strObjPtr);
+
+    if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) {
+        return NULL;
+    }
+
+    if (first == 0 && rangeLen == len) {
+        return strObjPtr;
+    }
+    if (len == bytelen) {
+        
+        return Jim_NewStringObj(interp, str + first, rangeLen);
+    }
+    return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen);
+#else
+    return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr);
+#endif
+}
+
+Jim_Obj *JimStringReplaceObj(Jim_Interp *interp,
+    Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr, Jim_Obj *newStrObj)
+{
+    int first, last;
+    const char *str;
+    int len, rangeLen;
+    Jim_Obj *objPtr;
+
+    len = Jim_Utf8Length(interp, strObjPtr);
+
+    if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) {
+        return NULL;
+    }
+
+    if (last < first) {
+        return strObjPtr;
+    }
+
+    str = Jim_String(strObjPtr);
+
+    
+    objPtr = Jim_NewStringObjUtf8(interp, str, first);
+
+    
+    if (newStrObj) {
+        Jim_AppendObj(interp, objPtr, newStrObj);
+    }
+
+    
+    Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
+
+    return objPtr;
+}
+
+static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
+{
+    while (*str) {
+        int c;
+        str += utf8_tounicode(str, &c);
+        dest += utf8_fromunicode(dest, uc ? utf8_upper(c) : utf8_lower(c));
+    }
+    *dest = 0;
+}
+
+static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
+{
+    char *buf;
+    int len;
+    const char *str;
+
+    SetStringFromAny(interp, strObjPtr);
+
+    str = Jim_GetString(strObjPtr, &len);
+
+#ifdef JIM_UTF8
+    len *= 2;
+#endif
+    buf = Jim_Alloc(len + 1);
+    JimStrCopyUpperLower(buf, str, 0);
+    return Jim_NewStringObjNoAlloc(interp, buf, -1);
+}
+
+static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
+{
+    char *buf;
+    const char *str;
+    int len;
+
+    if (strObjPtr->typePtr != &stringObjType) {
+        SetStringFromAny(interp, strObjPtr);
+    }
+
+    str = Jim_GetString(strObjPtr, &len);
+
+#ifdef JIM_UTF8
+    len *= 2;
+#endif
+    buf = Jim_Alloc(len + 1);
+    JimStrCopyUpperLower(buf, str, 1);
+    return Jim_NewStringObjNoAlloc(interp, buf, -1);
+}
+
+static Jim_Obj *JimStringToTitle(Jim_Interp *interp, Jim_Obj *strObjPtr)
+{
+    char *buf, *p;
+    int len;
+    int c;
+    const char *str;
+
+    str = Jim_GetString(strObjPtr, &len);
+    if (len == 0) {
+        return strObjPtr;
+    }
+#ifdef JIM_UTF8
+    len *= 2;
+#endif
+    buf = p = Jim_Alloc(len + 1);
+
+    str += utf8_tounicode(str, &c);
+    p += utf8_fromunicode(p, utf8_title(c));
+
+    JimStrCopyUpperLower(p, str, 0);
+
+    return Jim_NewStringObjNoAlloc(interp, buf, -1);
+}
+
+static const char *utf8_memchr(const char *str, int len, int c)
+{
+#ifdef JIM_UTF8
+    while (len) {
+        int sc;
+        int n = utf8_tounicode(str, &sc);
+        if (sc == c) {
+            return str;
+        }
+        str += n;
+        len -= n;
+    }
+    return NULL;
+#else
+    return memchr(str, c, len);
+#endif
+}
+
+static const char *JimFindTrimLeft(const char *str, int len, const char *trimchars, int trimlen)
+{
+    while (len) {
+        int c;
+        int n = utf8_tounicode(str, &c);
+
+        if (utf8_memchr(trimchars, trimlen, c) == NULL) {
+            
+            break;
+        }
+        str += n;
+        len -= n;
+    }
+    return str;
+}
+
+static const char *JimFindTrimRight(const char *str, int len, const char *trimchars, int trimlen)
+{
+    str += len;
+
+    while (len) {
+        int c;
+        int n = utf8_prev_len(str, len);
+
+        len -= n;
+        str -= n;
+
+        n = utf8_tounicode(str, &c);
+
+        if (utf8_memchr(trimchars, trimlen, c) == NULL) {
+            return str + n;
+        }
+    }
+
+    return NULL;
+}
+
+static const char default_trim_chars[] = " \t\n\r";
+
+static int default_trim_chars_len = sizeof(default_trim_chars);
+
+static Jim_Obj *JimStringTrimLeft(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
+{
+    int len;
+    const char *str = Jim_GetString(strObjPtr, &len);
+    const char *trimchars = default_trim_chars;
+    int trimcharslen = default_trim_chars_len;
+    const char *newstr;
+
+    if (trimcharsObjPtr) {
+        trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen);
+    }
+
+    newstr = JimFindTrimLeft(str, len, trimchars, trimcharslen);
+    if (newstr == str) {
+        return strObjPtr;
+    }
+
+    return Jim_NewStringObj(interp, newstr, len - (newstr - str));
+}
+
+static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
+{
+    int len;
+    const char *trimchars = default_trim_chars;
+    int trimcharslen = default_trim_chars_len;
+    const char *nontrim;
+
+    if (trimcharsObjPtr) {
+        trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen);
+    }
+
+    SetStringFromAny(interp, strObjPtr);
+
+    len = Jim_Length(strObjPtr);
+    nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
+
+    if (nontrim == NULL) {
+        
+        return Jim_NewEmptyStringObj(interp);
+    }
+    if (nontrim == strObjPtr->bytes + len) {
+        return strObjPtr;
+    }
+
+    if (Jim_IsShared(strObjPtr)) {
+        strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes));
+    }
+    else {
+        
+        strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0;
+        strObjPtr->length = (nontrim - strObjPtr->bytes);
+    }
+
+    return strObjPtr;
+}
+
+static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr)
+{
+    
+    Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr);
+
+    
+    strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
+
+    if (objPtr != strObjPtr) {
+        
+        Jim_IncrRefCount(objPtr);
+        Jim_DecrRefCount(interp, objPtr);
+    }
+
+    return strObjPtr;
+}
+
+
+#ifdef HAVE_ISASCII
+#define jim_isascii isascii
+#else
+static int jim_isascii(int c)
+{
+    return !(c & ~0x7f);
+}
+#endif
+
+static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
+{
+    static const char * const strclassnames[] = {
+        "integer", "alpha", "alnum", "ascii", "digit",
+        "double", "lower", "upper", "space", "xdigit",
+        "control", "print", "graph", "punct",
+        NULL
+    };
+    enum {
+        STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT,
+        STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT,
+        STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT
+    };
+    int strclass;
+    int len;
+    int i;
+    const char *str;
+    int (*isclassfunc)(int c) = NULL;
+
+    if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    str = Jim_GetString(strObjPtr, &len);
+    if (len == 0) {
+        Jim_SetResultInt(interp, !strict);
+        return JIM_OK;
+    }
+
+    switch (strclass) {
+        case STR_IS_INTEGER:
+            {
+                jim_wide w;
+                Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
+                return JIM_OK;
+            }
+
+        case STR_IS_DOUBLE:
+            {
+                double d;
+                Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
+                return JIM_OK;
+            }
+
+        case STR_IS_ALPHA: isclassfunc = isalpha; break;
+        case STR_IS_ALNUM: isclassfunc = isalnum; break;
+        case STR_IS_ASCII: isclassfunc = jim_isascii; break;
+        case STR_IS_DIGIT: isclassfunc = isdigit; break;
+        case STR_IS_LOWER: isclassfunc = islower; break;
+        case STR_IS_UPPER: isclassfunc = isupper; break;
+        case STR_IS_SPACE: isclassfunc = isspace; break;
+        case STR_IS_XDIGIT: isclassfunc = isxdigit; break;
+        case STR_IS_CONTROL: isclassfunc = iscntrl; break;
+        case STR_IS_PRINT: isclassfunc = isprint; break;
+        case STR_IS_GRAPH: isclassfunc = isgraph; break;
+        case STR_IS_PUNCT: isclassfunc = ispunct; break;
+        default:
+            return JIM_ERR;
+    }
+
+    for (i = 0; i < len; i++) {
+        if (!isclassfunc(str[i])) {
+            Jim_SetResultInt(interp, 0);
+            return JIM_OK;
+        }
+    }
+    Jim_SetResultInt(interp, 1);
+    return JIM_OK;
+}
+
+
+
+static const Jim_ObjType comparedStringObjType = {
+    "compared-string",
+    NULL,
+    NULL,
+    NULL,
+    JIM_TYPE_REFERENCES,
+};
+
+int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
+{
+    if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
+        return 1;
+    else {
+        const char *objStr = Jim_String(objPtr);
+
+        if (strcmp(str, objStr) != 0)
+            return 0;
+        if (objPtr->typePtr != &comparedStringObjType) {
+            Jim_FreeIntRep(interp, objPtr);
+            objPtr->typePtr = &comparedStringObjType;
+        }
+        objPtr->internalRep.ptr = (char *)str;  
+        return 1;
+    }
+}
+
+static int qsortCompareStringPointers(const void *a, const void *b)
+{
+    char *const *sa = (char *const *)a;
+    char *const *sb = (char *const *)b;
+
+    return strcmp(*sa, *sb);
+}
+
+
+
+static void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+static void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+
+static const Jim_ObjType sourceObjType = {
+    "source",
+    FreeSourceInternalRep,
+    DupSourceInternalRep,
+    NULL,
+    JIM_TYPE_REFERENCES,
+};
+
+void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_DecrRefCount(interp, objPtr->internalRep.sourceValue.fileNameObj);
+}
+
+void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    dupPtr->internalRep.sourceValue = srcPtr->internalRep.sourceValue;
+    Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj);
+}
+
+static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
+    Jim_Obj *fileNameObj, int lineNumber)
+{
+    JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
+    JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
+    Jim_IncrRefCount(fileNameObj);
+    objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
+    objPtr->internalRep.sourceValue.lineNumber = lineNumber;
+    objPtr->typePtr = &sourceObjType;
+}
+
+
+static const Jim_ObjType scriptLineObjType = {
+    "scriptline",
+    NULL,
+    NULL,
+    NULL,
+    0,
+};
+
+static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
+{
+    Jim_Obj *objPtr;
+
+#ifdef DEBUG_SHOW_SCRIPT
+    char buf[100];
+    snprintf(buf, sizeof(buf), "line=%d, argc=%d", line, argc);
+    objPtr = Jim_NewStringObj(interp, buf, -1);
+#else
+    objPtr = Jim_NewEmptyStringObj(interp);
+#endif
+    objPtr->typePtr = &scriptLineObjType;
+    objPtr->internalRep.scriptLineValue.argc = argc;
+    objPtr->internalRep.scriptLineValue.line = line;
+
+    return objPtr;
+}
+
+#define JIM_CMDSTRUCT_EXPAND -1
+
+static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
+
+static const Jim_ObjType scriptObjType = {
+    "script",
+    FreeScriptInternalRep,
+    DupScriptInternalRep,
+    NULL,
+    JIM_TYPE_REFERENCES,
+};
+
+typedef struct ScriptToken
+{
+    int type;
+    Jim_Obj *objPtr;
+} ScriptToken;
+
+typedef struct ScriptObj
+{
+    int len;                    
+    ScriptToken *token;         
+    int substFlags;             
+    int inUse;                  /* Used to share a ScriptObj. Currently
+                                   only used by Jim_EvalObj() as protection against
+                                   shimmering of the currently evaluated object. */
+    Jim_Obj *fileNameObj;
+    int firstline;              
+    int linenr;                 
+} ScriptObj;
+
+void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    int i;
+    struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
+
+    script->inUse--;
+    if (script->inUse != 0)
+        return;
+    for (i = 0; i < script->len; i++) {
+        Jim_DecrRefCount(interp, script->token[i].objPtr);
+    }
+    Jim_Free(script->token);
+    Jim_DecrRefCount(interp, script->fileNameObj);
+    Jim_Free(script);
+}
+
+void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    JIM_NOTUSED(interp);
+    JIM_NOTUSED(srcPtr);
+
+    
+    dupPtr->typePtr = NULL;
+}
+
+typedef struct
+{
+    const char *token;          
+    int len;                    
+    int type;                   
+    int line;                   
+} ParseToken;
+
+typedef struct
+{
+    
+    ParseToken *list;           
+    int size;                   
+    int count;                  
+    ParseToken static_list[20]; 
+} ParseTokenList;
+
+static void ScriptTokenListInit(ParseTokenList *tokenlist)
+{
+    tokenlist->list = tokenlist->static_list;
+    tokenlist->size = sizeof(tokenlist->static_list) / sizeof(ParseToken);
+    tokenlist->count = 0;
+}
+
+static void ScriptTokenListFree(ParseTokenList *tokenlist)
+{
+    if (tokenlist->list != tokenlist->static_list) {
+        Jim_Free(tokenlist->list);
+    }
+}
+
+static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len, int type,
+    int line)
+{
+    ParseToken *t;
+
+    if (tokenlist->count == tokenlist->size) {
+        
+        tokenlist->size *= 2;
+        if (tokenlist->list != tokenlist->static_list) {
+            tokenlist->list =
+                Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list));
+        }
+        else {
+            
+            tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list));
+            memcpy(tokenlist->list, tokenlist->static_list,
+                tokenlist->count * sizeof(*tokenlist->list));
+        }
+    }
+    t = &tokenlist->list[tokenlist->count++];
+    t->token = token;
+    t->len = len;
+    t->type = type;
+    t->line = line;
+}
+
+static int JimCountWordTokens(ParseToken *t)
+{
+    int expand = 1;
+    int count = 0;
+
+    
+    if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
+        if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
+            
+            expand = -1;
+            t++;
+        }
+    }
+
+    
+    while (!TOKEN_IS_SEP(t->type)) {
+        t++;
+        count++;
+    }
+
+    return count * expand;
+}
+
+static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
+{
+    Jim_Obj *objPtr;
+
+    if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
+        
+        int len = t->len;
+        char *str = Jim_Alloc(len + 1);
+        len = JimEscape(str, t->token, len);
+        objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
+    }
+    else {
+        objPtr = Jim_NewStringObj(interp, t->token, t->len);
+    }
+    return objPtr;
+}
+
+static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
+    ParseTokenList *tokenlist)
+{
+    int i;
+    struct ScriptToken *token;
+    
+    int lineargs = 0;
+    
+    ScriptToken *linefirst;
+    int count;
+    int linenr;
+
+#ifdef DEBUG_SHOW_SCRIPT_TOKENS
+    printf("==== Tokens ====\n");
+    for (i = 0; i < tokenlist->count; i++) {
+        printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type),
+            tokenlist->list[i].len, tokenlist->list[i].token);
+    }
+#endif
+
+    
+    count = tokenlist->count;
+    for (i = 0; i < tokenlist->count; i++) {
+        if (tokenlist->list[i].type == JIM_TT_EOL) {
+            count++;
+        }
+    }
+    linenr = script->firstline = tokenlist->list[0].line;
+
+    token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
+
+    
+    linefirst = token++;
+
+    for (i = 0; i < tokenlist->count; ) {
+        
+        int wordtokens;
+
+        
+        while (tokenlist->list[i].type == JIM_TT_SEP) {
+            i++;
+        }
+
+        wordtokens = JimCountWordTokens(tokenlist->list + i);
+
+        if (wordtokens == 0) {
+            
+            if (lineargs) {
+                linefirst->type = JIM_TT_LINE;
+                linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
+                Jim_IncrRefCount(linefirst->objPtr);
+
+                
+                lineargs = 0;
+                linefirst = token++;
+            }
+            i++;
+            continue;
+        }
+        else if (wordtokens != 1) {
+            
+            token->type = JIM_TT_WORD;
+            token->objPtr = Jim_NewIntObj(interp, wordtokens);
+            Jim_IncrRefCount(token->objPtr);
+            token++;
+            if (wordtokens < 0) {
+                
+                i++;
+                wordtokens = -wordtokens - 1;
+                lineargs--;
+            }
+        }
+
+        if (lineargs == 0) {
+            
+            linenr = tokenlist->list[i].line;
+        }
+        lineargs++;
+
+        
+        while (wordtokens--) {
+            const ParseToken *t = &tokenlist->list[i++];
+
+            token->type = t->type;
+            token->objPtr = JimMakeScriptObj(interp, t);
+            Jim_IncrRefCount(token->objPtr);
+
+            JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line);
+            token++;
+        }
+    }
+
+    if (lineargs == 0) {
+        token--;
+    }
+
+    script->len = token - script->token;
+
+    assert(script->len < count);
+
+#ifdef DEBUG_SHOW_SCRIPT
+    printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
+    for (i = 0; i < script->len; i++) {
+        const ScriptToken *t = &script->token[i];
+        printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
+    }
+#endif
+
+}
+
+static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
+    ParseTokenList *tokenlist)
+{
+    int i;
+    struct ScriptToken *token;
+
+    token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count);
+
+    for (i = 0; i < tokenlist->count; i++) {
+        const ParseToken *t = &tokenlist->list[i];
+
+        
+        token->type = t->type;
+        token->objPtr = JimMakeScriptObj(interp, t);
+        Jim_IncrRefCount(token->objPtr);
+        token++;
+    }
+
+    script->len = i;
+}
+
+static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
+{
+    int scriptTextLen;
+    const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
+    struct JimParserCtx parser;
+    struct ScriptObj *script;
+    ParseTokenList tokenlist;
+    int line = 1;
+
+    
+    if (objPtr->typePtr == &sourceObjType) {
+        line = objPtr->internalRep.sourceValue.lineNumber;
+    }
+
+    
+    ScriptTokenListInit(&tokenlist);
+
+    JimParserInit(&parser, scriptText, scriptTextLen, line);
+    while (!parser.eof) {
+        JimParseScript(&parser);
+        ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
+            parser.tline);
+    }
+    if (result && parser.missing != ' ') {
+        ScriptTokenListFree(&tokenlist);
+        result->missing = parser.missing;
+        result->line = parser.missingline;
+        return JIM_ERR;
+    }
+
+    
+    ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
+
+    
+    script = Jim_Alloc(sizeof(*script));
+    memset(script, 0, sizeof(*script));
+    script->inUse = 1;
+    if (objPtr->typePtr == &sourceObjType) {
+        script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
+    }
+    else {
+        script->fileNameObj = interp->emptyObj;
+    }
+    Jim_IncrRefCount(script->fileNameObj);
+
+    ScriptObjAddTokens(interp, script, &tokenlist);
+
+    
+    ScriptTokenListFree(&tokenlist);
+
+    
+    Jim_FreeIntRep(interp, objPtr);
+    Jim_SetIntRepPtr(objPtr, script);
+    objPtr->typePtr = &scriptObjType;
+
+    return JIM_OK;
+}
+
+ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    if (objPtr == interp->emptyObj) {
+        
+        objPtr = interp->nullScriptObj;
+    }
+
+    if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
+        SetScriptFromAny(interp, objPtr, NULL);
+    }
+    return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
+}
+
+static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr)
+{
+    cmdPtr->inUse++;
+}
+
+static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
+{
+    if (--cmdPtr->inUse == 0) {
+        if (cmdPtr->isproc) {
+            Jim_DecrRefCount(interp, cmdPtr->u.proc.argListObjPtr);
+            Jim_DecrRefCount(interp, cmdPtr->u.proc.bodyObjPtr);
+            Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
+            if (cmdPtr->u.proc.staticVars) {
+                Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
+                Jim_Free(cmdPtr->u.proc.staticVars);
+            }
+        }
+        else {
+            
+            if (cmdPtr->u.native.delProc) {
+                cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
+            }
+        }
+        if (cmdPtr->prevCmd) {
+            
+            JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
+        }
+        Jim_Free(cmdPtr);
+    }
+}
+
+
+static void JimVariablesHTValDestructor(void *interp, void *val)
+{
+    Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
+    Jim_Free(val);
+}
+
+static const Jim_HashTableType JimVariablesHashTableType = {
+    JimStringCopyHTHashFunction,        
+    JimStringCopyHTDup,                 
+    NULL,                               
+    JimStringCopyHTKeyCompare,  
+    JimStringCopyHTKeyDestructor,       
+    JimVariablesHTValDestructor 
+};
+
+static void JimCommandsHT_ValDestructor(void *interp, void *val)
+{
+    JimDecrCmdRefCount(interp, val);
+}
+
+static const Jim_HashTableType JimCommandsHashTableType = {
+    JimStringCopyHTHashFunction,    
+    JimStringCopyHTDup,             
+    NULL,                           
+    JimStringCopyHTKeyCompare,      
+    JimStringCopyHTKeyDestructor,   
+    JimCommandsHT_ValDestructor     
+};
+
+
+
+#ifdef jim_ext_namespace
+static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
+{
+    const char *name = Jim_String(nsObj);
+    if (name[0] == ':' && name[1] == ':') {
+        
+        while (*++name == ':') {
+        }
+        nsObj = Jim_NewStringObj(interp, name, -1);
+    }
+    else if (Jim_Length(interp->framePtr->nsObj)) {
+        
+        nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
+        Jim_AppendStrings(interp, nsObj, "::", name, NULL);
+    }
+    return nsObj;
+}
+
+static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
+{
+    Jim_Obj *objPtr = interp->emptyObj;
+
+    if (name[0] == ':' && name[1] == ':') {
+        
+        while (*++name == ':') {
+        }
+    }
+    else if (Jim_Length(interp->framePtr->nsObj)) {
+        
+        objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
+        Jim_AppendStrings(interp, objPtr, "::", name, NULL);
+        name = Jim_String(objPtr);
+    }
+    Jim_IncrRefCount(objPtr);
+    *objPtrPtr = objPtr;
+    return name;
+}
+
+    #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
+
+#else
+    
+    #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
+    #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
+#endif
+
+static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
+{
+    Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
+    if (he) {
+
+        Jim_InterpIncrProcEpoch(interp);
+    }
+
+    if (he && interp->local) {
+        
+        cmd->prevCmd = he->u.val;
+        he->u.val = cmd;
+    }
+    else {
+        if (he) {
+            
+            Jim_DeleteHashEntry(&interp->commands, name);
+        }
+
+        Jim_AddHashEntry(&interp->commands, name, cmd);
+    }
+    return JIM_OK;
+}
+
+
+int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
+    Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc)
+{
+    Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
+
+    
+    memset(cmdPtr, 0, sizeof(*cmdPtr));
+    cmdPtr->inUse = 1;
+    cmdPtr->u.native.delProc = delProc;
+    cmdPtr->u.native.cmdProc = cmdProc;
+    cmdPtr->u.native.privData = privData;
+
+    JimCreateCommand(interp, cmdNameStr, cmdPtr);
+
+    return JIM_OK;
+}
+
+static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *staticsListObjPtr)
+{
+    int len, i;
+
+    len = Jim_ListLength(interp, staticsListObjPtr);
+    if (len == 0) {
+        return JIM_OK;
+    }
+
+    cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
+    Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
+    for (i = 0; i < len; i++) {
+        Jim_Obj *objPtr = NULL, *initObjPtr = NULL, *nameObjPtr = NULL;
+        Jim_Var *varPtr;
+        int subLen;
+
+        Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
+        
+        subLen = Jim_ListLength(interp, objPtr);
+        if (subLen == 1 || subLen == 2) {
+            Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
+            if (subLen == 1) {
+                initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
+                if (initObjPtr == NULL) {
+                    Jim_SetResultFormatted(interp,
+                        "variable for initialization of static \"%#s\" not found in the local context",
+                        nameObjPtr);
+                    return JIM_ERR;
+                }
+            }
+            else {
+                Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
+            }
+            if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
+                return JIM_ERR;
+            }
+
+            varPtr = Jim_Alloc(sizeof(*varPtr));
+            varPtr->objPtr = initObjPtr;
+            Jim_IncrRefCount(initObjPtr);
+            varPtr->linkFramePtr = NULL;
+            if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars,
+                Jim_String(nameObjPtr), varPtr) != JIM_OK) {
+                Jim_SetResultFormatted(interp,
+                    "static variable name \"%#s\" duplicated in statics list", nameObjPtr);
+                Jim_DecrRefCount(interp, initObjPtr);
+                Jim_Free(varPtr);
+                return JIM_ERR;
+            }
+        }
+        else {
+            Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"",
+                objPtr);
+            return JIM_ERR;
+        }
+    }
+    return JIM_OK;
+}
+
+static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
+{
+#ifdef jim_ext_namespace
+    if (cmdPtr->isproc) {
+        
+        const char *pt = strrchr(cmdname, ':');
+        if (pt && pt != cmdname && pt[-1] == ':') {
+            Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
+            cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
+            Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
+
+            if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
+                
+                Jim_InterpIncrProcEpoch(interp);
+            }
+        }
+    }
+#endif
+}
+
+static Jim_Cmd *JimCreateProcedureCmd(Jim_Interp *interp, Jim_Obj *argListObjPtr,
+    Jim_Obj *staticsListObjPtr, Jim_Obj *bodyObjPtr, Jim_Obj *nsObj)
+{
+    Jim_Cmd *cmdPtr;
+    int argListLen;
+    int i;
+
+    argListLen = Jim_ListLength(interp, argListObjPtr);
+
+    
+    cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen);
+    memset(cmdPtr, 0, sizeof(*cmdPtr));
+    cmdPtr->inUse = 1;
+    cmdPtr->isproc = 1;
+    cmdPtr->u.proc.argListObjPtr = argListObjPtr;
+    cmdPtr->u.proc.argListLen = argListLen;
+    cmdPtr->u.proc.bodyObjPtr = bodyObjPtr;
+    cmdPtr->u.proc.argsPos = -1;
+    cmdPtr->u.proc.arglist = (struct Jim_ProcArg *)(cmdPtr + 1);
+    cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
+    Jim_IncrRefCount(argListObjPtr);
+    Jim_IncrRefCount(bodyObjPtr);
+    Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
+
+    
+    if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
+        goto err;
+    }
+
+    
+    
+    for (i = 0; i < argListLen; i++) {
+        Jim_Obj *argPtr;
+        Jim_Obj *nameObjPtr;
+        Jim_Obj *defaultObjPtr;
+        int len;
+
+        
+        Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
+        len = Jim_ListLength(interp, argPtr);
+        if (len == 0) {
+            Jim_SetResultString(interp, "argument with no name", -1);
+err:
+            JimDecrCmdRefCount(interp, cmdPtr);
+            return NULL;
+        }
+        if (len > 2) {
+            Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
+            goto err;
+        }
+
+        if (len == 2) {
+            
+            Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
+            Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
+        }
+        else {
+            
+            nameObjPtr = argPtr;
+            defaultObjPtr = NULL;
+        }
+
+
+        if (Jim_CompareStringImmediate(interp, nameObjPtr, "args")) {
+            if (cmdPtr->u.proc.argsPos >= 0) {
+                Jim_SetResultString(interp, "'args' specified more than once", -1);
+                goto err;
+            }
+            cmdPtr->u.proc.argsPos = i;
+        }
+        else {
+            if (len == 2) {
+                cmdPtr->u.proc.optArity++;
+            }
+            else {
+                cmdPtr->u.proc.reqArity++;
+            }
+        }
+
+        cmdPtr->u.proc.arglist[i].nameObjPtr = nameObjPtr;
+        cmdPtr->u.proc.arglist[i].defaultObjPtr = defaultObjPtr;
+    }
+
+    return cmdPtr;
+}
+
+int Jim_DeleteCommand(Jim_Interp *interp, const char *name)
+{
+    int ret = JIM_OK;
+    Jim_Obj *qualifiedNameObj;
+    const char *qualname = JimQualifyName(interp, name, &qualifiedNameObj);
+
+    if (Jim_DeleteHashEntry(&interp->commands, qualname) == JIM_ERR) {
+        Jim_SetResultFormatted(interp, "can't delete \"%s\": command doesn't exist", name);
+        ret = JIM_ERR;
+    }
+    else {
+        Jim_InterpIncrProcEpoch(interp);
+    }
+
+    JimFreeQualifiedName(interp, qualifiedNameObj);
+
+    return ret;
+}
+
+int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName)
+{
+    int ret = JIM_ERR;
+    Jim_HashEntry *he;
+    Jim_Cmd *cmdPtr;
+    Jim_Obj *qualifiedOldNameObj;
+    Jim_Obj *qualifiedNewNameObj;
+    const char *fqold;
+    const char *fqnew;
+
+    if (newName[0] == 0) {
+        return Jim_DeleteCommand(interp, oldName);
+    }
+
+    fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
+    fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
+
+    
+    he = Jim_FindHashEntry(&interp->commands, fqold);
+    if (he == NULL) {
+        Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
+    }
+    else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
+        Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
+    }
+    else {
+        
+        cmdPtr = he->u.val;
+        JimIncrCmdRefCount(cmdPtr);
+        JimUpdateProcNamespace(interp, cmdPtr, fqnew);
+        Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
+
+        
+        Jim_DeleteHashEntry(&interp->commands, fqold);
+
+        
+        Jim_InterpIncrProcEpoch(interp);
+
+        ret = JIM_OK;
+    }
+
+    JimFreeQualifiedName(interp, qualifiedOldNameObj);
+    JimFreeQualifiedName(interp, qualifiedNewNameObj);
+
+    return ret;
+}
+
+
+static void FreeCommandInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_DecrRefCount(interp, objPtr->internalRep.cmdValue.nsObj);
+}
+
+static void DupCommandInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    dupPtr->internalRep.cmdValue = srcPtr->internalRep.cmdValue;
+    dupPtr->typePtr = srcPtr->typePtr;
+    Jim_IncrRefCount(dupPtr->internalRep.cmdValue.nsObj);
+}
+
+static const Jim_ObjType commandObjType = {
+    "command",
+    FreeCommandInternalRep,
+    DupCommandInternalRep,
+    NULL,
+    JIM_TYPE_REFERENCES,
+};
+
+Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
+{
+    Jim_Cmd *cmd;
+
+    if (objPtr->typePtr != &commandObjType ||
+            objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
+#ifdef jim_ext_namespace
+            || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
+#endif
+        ) {
+        
+
+        
+        const char *name = Jim_String(objPtr);
+        Jim_HashEntry *he;
+
+        if (name[0] == ':' && name[1] == ':') {
+            while (*++name == ':') {
+            }
+        }
+#ifdef jim_ext_namespace
+        else if (Jim_Length(interp->framePtr->nsObj)) {
+            
+            Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
+            Jim_AppendStrings(interp, nameObj, "::", name, NULL);
+            he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
+            Jim_FreeNewObj(interp, nameObj);
+            if (he) {
+                goto found;
+            }
+        }
+#endif
+
+        
+        he = Jim_FindHashEntry(&interp->commands, name);
+        if (he == NULL) {
+            if (flags & JIM_ERRMSG) {
+                Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
+            }
+            return NULL;
+        }
+#ifdef jim_ext_namespace
+found:
+#endif
+        cmd = (Jim_Cmd *)he->u.val;
+
+        
+        Jim_FreeIntRep(interp, objPtr);
+        objPtr->typePtr = &commandObjType;
+        objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
+        objPtr->internalRep.cmdValue.cmdPtr = cmd;
+        objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
+        Jim_IncrRefCount(interp->framePtr->nsObj);
+    }
+    else {
+        cmd = objPtr->internalRep.cmdValue.cmdPtr;
+    }
+    while (cmd->u.proc.upcall) {
+        cmd = cmd->prevCmd;
+    }
+    return cmd;
+}
+
+
+
+#define JIM_DICT_SUGAR 100      
+
+static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+
+static const Jim_ObjType variableObjType = {
+    "variable",
+    NULL,
+    NULL,
+    NULL,
+    JIM_TYPE_REFERENCES,
+};
+
+static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr)
+{
+    
+    if (nameObjPtr->typePtr != &variableObjType) {
+        int len;
+        const char *str = Jim_GetString(nameObjPtr, &len);
+        if (memchr(str, '\0', len)) {
+            Jim_SetResultFormatted(interp, "%s name contains embedded null", type);
+            return JIM_ERR;
+        }
+    }
+    return JIM_OK;
+}
+
+static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
+{
+    const char *varName;
+    Jim_CallFrame *framePtr;
+    Jim_HashEntry *he;
+    int global;
+    int len;
+
+    
+    if (objPtr->typePtr == &variableObjType) {
+        framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
+        if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
+            
+            return JIM_OK;
+        }
+        
+    }
+    else if (objPtr->typePtr == &dictSubstObjType) {
+        return JIM_DICT_SUGAR;
+    }
+    else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+
+    varName = Jim_GetString(objPtr, &len);
+
+    
+    if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
+        return JIM_DICT_SUGAR;
+    }
+
+    if (varName[0] == ':' && varName[1] == ':') {
+        while (*++varName == ':') {
+        }
+        global = 1;
+        framePtr = interp->topFramePtr;
+    }
+    else {
+        global = 0;
+        framePtr = interp->framePtr;
+    }
+
+    
+    he = Jim_FindHashEntry(&framePtr->vars, varName);
+    if (he == NULL) {
+        if (!global && framePtr->staticVars) {
+            
+            he = Jim_FindHashEntry(framePtr->staticVars, varName);
+        }
+        if (he == NULL) {
+            return JIM_ERR;
+        }
+    }
+
+    
+    Jim_FreeIntRep(interp, objPtr);
+    objPtr->typePtr = &variableObjType;
+    objPtr->internalRep.varValue.callFrameId = framePtr->id;
+    objPtr->internalRep.varValue.varPtr = he->u.val;
+    objPtr->internalRep.varValue.global = global;
+    return JIM_OK;
+}
+
+
+static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
+static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
+
+static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
+{
+    const char *name;
+    Jim_CallFrame *framePtr;
+    int global;
+
+    
+    Jim_Var *var = Jim_Alloc(sizeof(*var));
+
+    var->objPtr = valObjPtr;
+    Jim_IncrRefCount(valObjPtr);
+    var->linkFramePtr = NULL;
+
+    name = Jim_String(nameObjPtr);
+    if (name[0] == ':' && name[1] == ':') {
+        while (*++name == ':') {
+        }
+        framePtr = interp->topFramePtr;
+        global = 1;
+    }
+    else {
+        framePtr = interp->framePtr;
+        global = 0;
+    }
+
+    
+    Jim_AddHashEntry(&framePtr->vars, name, var);
+
+    
+    Jim_FreeIntRep(interp, nameObjPtr);
+    nameObjPtr->typePtr = &variableObjType;
+    nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
+    nameObjPtr->internalRep.varValue.varPtr = var;
+    nameObjPtr->internalRep.varValue.global = global;
+
+    return var;
+}
+
+
+int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
+{
+    int err;
+    Jim_Var *var;
+
+    switch (SetVariableFromAny(interp, nameObjPtr)) {
+        case JIM_DICT_SUGAR:
+            return JimDictSugarSet(interp, nameObjPtr, valObjPtr);
+
+        case JIM_ERR:
+            if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) {
+                return JIM_ERR;
+            }
+            JimCreateVariable(interp, nameObjPtr, valObjPtr);
+            break;
+
+        case JIM_OK:
+            var = nameObjPtr->internalRep.varValue.varPtr;
+            if (var->linkFramePtr == NULL) {
+                Jim_IncrRefCount(valObjPtr);
+                Jim_DecrRefCount(interp, var->objPtr);
+                var->objPtr = valObjPtr;
+            }
+            else {                  
+                Jim_CallFrame *savedCallFrame;
+
+                savedCallFrame = interp->framePtr;
+                interp->framePtr = var->linkFramePtr;
+                err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
+                interp->framePtr = savedCallFrame;
+                if (err != JIM_OK)
+                    return err;
+            }
+    }
+    return JIM_OK;
+}
+
+int Jim_SetVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr)
+{
+    Jim_Obj *nameObjPtr;
+    int result;
+
+    nameObjPtr = Jim_NewStringObj(interp, name, -1);
+    Jim_IncrRefCount(nameObjPtr);
+    result = Jim_SetVariable(interp, nameObjPtr, objPtr);
+    Jim_DecrRefCount(interp, nameObjPtr);
+    return result;
+}
+
+int Jim_SetGlobalVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr)
+{
+    Jim_CallFrame *savedFramePtr;
+    int result;
+
+    savedFramePtr = interp->framePtr;
+    interp->framePtr = interp->topFramePtr;
+    result = Jim_SetVariableStr(interp, name, objPtr);
+    interp->framePtr = savedFramePtr;
+    return result;
+}
+
+int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val)
+{
+    Jim_Obj *nameObjPtr, *valObjPtr;
+    int result;
+
+    nameObjPtr = Jim_NewStringObj(interp, name, -1);
+    valObjPtr = Jim_NewStringObj(interp, val, -1);
+    Jim_IncrRefCount(nameObjPtr);
+    Jim_IncrRefCount(valObjPtr);
+    result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
+    Jim_DecrRefCount(interp, nameObjPtr);
+    Jim_DecrRefCount(interp, valObjPtr);
+    return result;
+}
+
+int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
+    Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame)
+{
+    const char *varName;
+    const char *targetName;
+    Jim_CallFrame *framePtr;
+    Jim_Var *varPtr;
+
+    
+    switch (SetVariableFromAny(interp, nameObjPtr)) {
+        case JIM_DICT_SUGAR:
+            
+            Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
+            return JIM_ERR;
+
+        case JIM_OK:
+            varPtr = nameObjPtr->internalRep.varValue.varPtr;
+
+            if (varPtr->linkFramePtr == NULL) {
+                Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
+                return JIM_ERR;
+            }
+
+            
+            varPtr->linkFramePtr = NULL;
+            break;
+    }
+
+    
+    
+    varName = Jim_String(nameObjPtr);
+
+    if (varName[0] == ':' && varName[1] == ':') {
+        while (*++varName == ':') {
+        }
+        
+        framePtr = interp->topFramePtr;
+    }
+    else {
+        framePtr = interp->framePtr;
+    }
+
+    targetName = Jim_String(targetNameObjPtr);
+    if (targetName[0] == ':' && targetName[1] == ':') {
+        while (*++targetName == ':') {
+        }
+        targetNameObjPtr = Jim_NewStringObj(interp, targetName, -1);
+        targetCallFrame = interp->topFramePtr;
+    }
+    Jim_IncrRefCount(targetNameObjPtr);
+
+    if (framePtr->level < targetCallFrame->level) {
+        Jim_SetResultFormatted(interp,
+            "bad variable name \"%#s\": upvar won't create namespace variable that refers to procedure variable",
+            nameObjPtr);
+        Jim_DecrRefCount(interp, targetNameObjPtr);
+        return JIM_ERR;
+    }
+
+    
+    if (framePtr == targetCallFrame) {
+        Jim_Obj *objPtr = targetNameObjPtr;
+
+        
+        while (1) {
+            if (strcmp(Jim_String(objPtr), varName) == 0) {
+                Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
+                Jim_DecrRefCount(interp, targetNameObjPtr);
+                return JIM_ERR;
+            }
+            if (SetVariableFromAny(interp, objPtr) != JIM_OK)
+                break;
+            varPtr = objPtr->internalRep.varValue.varPtr;
+            if (varPtr->linkFramePtr != targetCallFrame)
+                break;
+            objPtr = varPtr->objPtr;
+        }
+    }
+
+    
+    Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
+    
+    nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
+    Jim_DecrRefCount(interp, targetNameObjPtr);
+    return JIM_OK;
+}
+
+Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
+{
+    switch (SetVariableFromAny(interp, nameObjPtr)) {
+        case JIM_OK:{
+                Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr;
+
+                if (varPtr->linkFramePtr == NULL) {
+                    return varPtr->objPtr;
+                }
+                else {
+                    Jim_Obj *objPtr;
+
+                    
+                    Jim_CallFrame *savedCallFrame = interp->framePtr;
+
+                    interp->framePtr = varPtr->linkFramePtr;
+                    objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags);
+                    interp->framePtr = savedCallFrame;
+                    if (objPtr) {
+                        return objPtr;
+                    }
+                    
+                }
+            }
+            break;
+
+        case JIM_DICT_SUGAR:
+            
+            return JimDictSugarGet(interp, nameObjPtr, flags);
+    }
+    if (flags & JIM_ERRMSG) {
+        Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr);
+    }
+    return NULL;
+}
+
+Jim_Obj *Jim_GetGlobalVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
+{
+    Jim_CallFrame *savedFramePtr;
+    Jim_Obj *objPtr;
+
+    savedFramePtr = interp->framePtr;
+    interp->framePtr = interp->topFramePtr;
+    objPtr = Jim_GetVariable(interp, nameObjPtr, flags);
+    interp->framePtr = savedFramePtr;
+
+    return objPtr;
+}
+
+Jim_Obj *Jim_GetVariableStr(Jim_Interp *interp, const char *name, int flags)
+{
+    Jim_Obj *nameObjPtr, *varObjPtr;
+
+    nameObjPtr = Jim_NewStringObj(interp, name, -1);
+    Jim_IncrRefCount(nameObjPtr);
+    varObjPtr = Jim_GetVariable(interp, nameObjPtr, flags);
+    Jim_DecrRefCount(interp, nameObjPtr);
+    return varObjPtr;
+}
+
+Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flags)
+{
+    Jim_CallFrame *savedFramePtr;
+    Jim_Obj *objPtr;
+
+    savedFramePtr = interp->framePtr;
+    interp->framePtr = interp->topFramePtr;
+    objPtr = Jim_GetVariableStr(interp, name, flags);
+    interp->framePtr = savedFramePtr;
+
+    return objPtr;
+}
+
+int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
+{
+    Jim_Var *varPtr;
+    int retval;
+    Jim_CallFrame *framePtr;
+
+    retval = SetVariableFromAny(interp, nameObjPtr);
+    if (retval == JIM_DICT_SUGAR) {
+        
+        return JimDictSugarSet(interp, nameObjPtr, NULL);
+    }
+    else if (retval == JIM_OK) {
+        varPtr = nameObjPtr->internalRep.varValue.varPtr;
+
+        
+        if (varPtr->linkFramePtr) {
+            framePtr = interp->framePtr;
+            interp->framePtr = varPtr->linkFramePtr;
+            retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
+            interp->framePtr = framePtr;
+        }
+        else {
+            const char *name = Jim_String(nameObjPtr);
+            if (nameObjPtr->internalRep.varValue.global) {
+                name += 2;
+                framePtr = interp->topFramePtr;
+            }
+            else {
+                framePtr = interp->framePtr;
+            }
+
+            retval = Jim_DeleteHashEntry(&framePtr->vars, name);
+            if (retval == JIM_OK) {
+                
+                JimChangeCallFrameId(interp, framePtr);
+            }
+        }
+    }
+    if (retval != JIM_OK && (flags & JIM_ERRMSG)) {
+        Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr);
+    }
+    return retval;
+}
+
+
+
+static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr,
+    Jim_Obj **varPtrPtr, Jim_Obj **keyPtrPtr)
+{
+    const char *str, *p;
+    int len, keyLen;
+    Jim_Obj *varObjPtr, *keyObjPtr;
+
+    str = Jim_GetString(objPtr, &len);
+
+    p = strchr(str, '(');
+    JimPanic((p == NULL, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str));
+
+    varObjPtr = Jim_NewStringObj(interp, str, p - str);
+
+    p++;
+    keyLen = (str + len) - p;
+    if (str[len - 1] == ')') {
+        keyLen--;
+    }
+
+    
+    keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
+
+    Jim_IncrRefCount(varObjPtr);
+    Jim_IncrRefCount(keyObjPtr);
+    *varPtrPtr = varObjPtr;
+    *keyPtrPtr = keyObjPtr;
+}
+
+static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjPtr)
+{
+    int err;
+
+    SetDictSubstFromAny(interp, objPtr);
+
+    err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
+        &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
+
+    if (err == JIM_OK) {
+        
+        Jim_SetEmptyResult(interp);
+    }
+    else {
+        if (!valObjPtr) {
+            
+            if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) {
+                Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array",
+                    objPtr);
+                return err;
+            }
+        }
+        
+        Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array",
+            (valObjPtr ? "set" : "unset"), objPtr);
+    }
+    return err;
+}
+
+static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPtr,
+    Jim_Obj *keyObjPtr, int flags)
+{
+    Jim_Obj *dictObjPtr;
+    Jim_Obj *resObjPtr = NULL;
+    int ret;
+
+    dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG);
+    if (!dictObjPtr) {
+        return NULL;
+    }
+
+    ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
+    if (ret != JIM_OK) {
+        resObjPtr = NULL;
+        if (ret < 0) {
+            Jim_SetResultFormatted(interp,
+                "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
+        }
+        else {
+            Jim_SetResultFormatted(interp,
+                "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
+        }
+    }
+    else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
+        dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
+        if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
+            
+            JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
+        }
+        
+        Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
+    }
+
+    return resObjPtr;
+}
+
+
+static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
+{
+    SetDictSubstFromAny(interp, objPtr);
+
+    return JimDictExpandArrayVariable(interp,
+        objPtr->internalRep.dictSubstValue.varNameObjPtr,
+        objPtr->internalRep.dictSubstValue.indexObjPtr, flags);
+}
+
+
+
+void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr);
+    Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
+}
+
+void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    JIM_NOTUSED(interp);
+
+    dupPtr->internalRep.dictSubstValue.varNameObjPtr =
+        srcPtr->internalRep.dictSubstValue.varNameObjPtr;
+    dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr;
+    dupPtr->typePtr = &dictSubstObjType;
+}
+
+
+static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    if (objPtr->typePtr != &dictSubstObjType) {
+        Jim_Obj *varObjPtr, *keyObjPtr;
+
+        if (objPtr->typePtr == &interpolatedObjType) {
+            
+
+            varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
+            keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
+
+            Jim_IncrRefCount(varObjPtr);
+            Jim_IncrRefCount(keyObjPtr);
+        }
+        else {
+            JimDictSugarParseVarKey(interp, objPtr, &varObjPtr, &keyObjPtr);
+        }
+
+        Jim_FreeIntRep(interp, objPtr);
+        objPtr->typePtr = &dictSubstObjType;
+        objPtr->internalRep.dictSubstValue.varNameObjPtr = varObjPtr;
+        objPtr->internalRep.dictSubstValue.indexObjPtr = keyObjPtr;
+    }
+}
+
+static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_Obj *resObjPtr = NULL;
+    Jim_Obj *substKeyObjPtr = NULL;
+
+    SetDictSubstFromAny(interp, objPtr);
+
+    if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr,
+            &substKeyObjPtr, JIM_NONE)
+        != JIM_OK) {
+        return NULL;
+    }
+    Jim_IncrRefCount(substKeyObjPtr);
+    resObjPtr =
+        JimDictExpandArrayVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
+        substKeyObjPtr, 0);
+    Jim_DecrRefCount(interp, substKeyObjPtr);
+
+    return resObjPtr;
+}
+
+static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_Obj *resultObjPtr;
+
+    if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) {
+        
+        resultObjPtr->refCount--;
+        return resultObjPtr;
+    }
+    return NULL;
+}
+
+
+static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj)
+{
+    Jim_CallFrame *cf;
+
+    if (interp->freeFramesList) {
+        cf = interp->freeFramesList;
+        interp->freeFramesList = cf->next;
+    }
+    else {
+        cf = Jim_Alloc(sizeof(*cf));
+        cf->vars.table = NULL;
+    }
+
+    cf->id = interp->callFrameEpoch++;
+    cf->parent = parent;
+    cf->level = parent ? parent->level + 1 : 0;
+    cf->argv = NULL;
+    cf->argc = 0;
+    cf->procArgsObjPtr = NULL;
+    cf->procBodyObjPtr = NULL;
+    cf->next = NULL;
+    cf->staticVars = NULL;
+    cf->localCommands = NULL;
+
+    cf->nsObj = nsObj;
+    Jim_IncrRefCount(nsObj);
+    if (cf->vars.table == NULL)
+        Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
+    return cf;
+}
+
+
+static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
+{
+    cf->id = interp->callFrameEpoch++;
+}
+
+static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
+{
+    
+    if (localCommands) {
+        Jim_Obj *cmdNameObj;
+
+        while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
+            Jim_HashEntry *he;
+            Jim_Obj *fqObjName;
+
+            const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
+
+            he = Jim_FindHashEntry(&interp->commands, fqname);
+
+            if (he) {
+                Jim_Cmd *cmd = he->u.val;
+                if (cmd->prevCmd) {
+                    Jim_Cmd *prevCmd = cmd->prevCmd;
+                    cmd->prevCmd = NULL;
+
+                    
+                    JimDecrCmdRefCount(interp, cmd);
+
+                    
+                    he->u.val = prevCmd;
+                }
+                else {
+                    Jim_DeleteHashEntry(&interp->commands, fqname);
+                    Jim_InterpIncrProcEpoch(interp);
+                }
+            }
+            Jim_DecrRefCount(interp, cmdNameObj);
+            JimFreeQualifiedName(interp, fqObjName);
+        }
+        Jim_FreeStack(localCommands);
+        Jim_Free(localCommands);
+    }
+    return JIM_OK;
+}
+
+
+#define JIM_FCF_NONE 0          
+#define JIM_FCF_NOHT 1          
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
+{
+    if (cf->procArgsObjPtr)
+        Jim_DecrRefCount(interp, cf->procArgsObjPtr);
+    if (cf->procBodyObjPtr)
+        Jim_DecrRefCount(interp, cf->procBodyObjPtr);
+    Jim_DecrRefCount(interp, cf->nsObj);
+    if (!(flags & JIM_FCF_NOHT))
+        Jim_FreeHashTable(&cf->vars);
+    else {
+        int i;
+        Jim_HashEntry **table = cf->vars.table, *he;
+
+        for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) {
+            he = table[i];
+            while (he != NULL) {
+                Jim_HashEntry *nextEntry = he->next;
+                Jim_Var *varPtr = (void *)he->u.val;
+
+                Jim_DecrRefCount(interp, varPtr->objPtr);
+                Jim_Free(he->u.val);
+                Jim_Free((void *)he->key);      
+                Jim_Free(he);
+                table[i] = NULL;
+                he = nextEntry;
+            }
+        }
+        cf->vars.used = 0;
+    }
+
+    JimDeleteLocalProcs(interp, cf->localCommands);
+
+    cf->next = interp->freeFramesList;
+    interp->freeFramesList = cf;
+
+}
+
+
+#ifdef JIM_REFERENCES
+
+static void JimReferencesHTValDestructor(void *interp, void *val)
+{
+    Jim_Reference *refPtr = (void *)val;
+
+    Jim_DecrRefCount(interp, refPtr->objPtr);
+    if (refPtr->finalizerCmdNamePtr != NULL) {
+        Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
+    }
+    Jim_Free(val);
+}
+
+static unsigned int JimReferencesHTHashFunction(const void *key)
+{
+    
+    const unsigned long *widePtr = key;
+    unsigned int intValue = (unsigned int)*widePtr;
+
+    return Jim_IntHashFunction(intValue);
+}
+
+static void *JimReferencesHTKeyDup(void *privdata, const void *key)
+{
+    void *copy = Jim_Alloc(sizeof(unsigned long));
+
+    JIM_NOTUSED(privdata);
+
+    memcpy(copy, key, sizeof(unsigned long));
+    return copy;
+}
+
+static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2)
+{
+    JIM_NOTUSED(privdata);
+
+    return memcmp(key1, key2, sizeof(unsigned long)) == 0;
+}
+
+static void JimReferencesHTKeyDestructor(void *privdata, void *key)
+{
+    JIM_NOTUSED(privdata);
+
+    Jim_Free(key);
+}
+
+static const Jim_HashTableType JimReferencesHashTableType = {
+    JimReferencesHTHashFunction,        
+    JimReferencesHTKeyDup,      
+    NULL,                       
+    JimReferencesHTKeyCompare,  
+    JimReferencesHTKeyDestructor,       
+    JimReferencesHTValDestructor        
+};
+
+
+
+#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)
+
+static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id)
+{
+    const char *fmt = "<reference.<%s>.%020lu>";
+
+    sprintf(buf, fmt, refPtr->tag, id);
+    return JIM_REFERENCE_SPACE;
+}
+
+static void UpdateStringOfReference(struct Jim_Obj *objPtr);
+
+static const Jim_ObjType referenceObjType = {
+    "reference",
+    NULL,
+    NULL,
+    UpdateStringOfReference,
+    JIM_TYPE_REFERENCES,
+};
+
+void UpdateStringOfReference(struct Jim_Obj *objPtr)
+{
+    int len;
+    char buf[JIM_REFERENCE_SPACE + 1];
+    Jim_Reference *refPtr;
+
+    refPtr = objPtr->internalRep.refValue.refPtr;
+    len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
+    objPtr->bytes = Jim_Alloc(len + 1);
+    memcpy(objPtr->bytes, buf, len + 1);
+    objPtr->length = len;
+}
+
+static int isrefchar(int c)
+{
+    return (c == '_' || isalnum(c));
+}
+
+static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    unsigned long value;
+    int i, len;
+    const char *str, *start, *end;
+    char refId[21];
+    Jim_Reference *refPtr;
+    Jim_HashEntry *he;
+    char *endptr;
+
+    
+    str = Jim_GetString(objPtr, &len);
+    
+    if (len < JIM_REFERENCE_SPACE)
+        goto badformat;
+    
+    start = str;
+    end = str + len - 1;
+    while (*start == ' ')
+        start++;
+    while (*end == ' ' && end > start)
+        end--;
+    if (end - start + 1 != JIM_REFERENCE_SPACE)
+        goto badformat;
+    
+    if (memcmp(start, "<reference.<", 12) != 0)
+        goto badformat;
+    if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>')
+        goto badformat;
+    
+    for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
+        if (!isrefchar(start[12 + i]))
+            goto badformat;
+    }
+    
+    memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20);
+    refId[20] = '\0';
+    
+    value = strtoul(refId, &endptr, 10);
+    if (JimCheckConversion(refId, endptr) != JIM_OK)
+        goto badformat;
+    
+    he = Jim_FindHashEntry(&interp->references, &value);
+    if (he == NULL) {
+        Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
+        return JIM_ERR;
+    }
+    refPtr = he->u.val;
+    
+    Jim_FreeIntRep(interp, objPtr);
+    objPtr->typePtr = &referenceObjType;
+    objPtr->internalRep.refValue.id = value;
+    objPtr->internalRep.refValue.refPtr = refPtr;
+    return JIM_OK;
+
+  badformat:
+    Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr);
+    return JIM_ERR;
+}
+
+Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr)
+{
+    struct Jim_Reference *refPtr;
+    unsigned long id;
+    Jim_Obj *refObjPtr;
+    const char *tag;
+    int tagLen, i;
+
+    
+    Jim_CollectIfNeeded(interp);
+
+    refPtr = Jim_Alloc(sizeof(*refPtr));
+    refPtr->objPtr = objPtr;
+    Jim_IncrRefCount(objPtr);
+    refPtr->finalizerCmdNamePtr = cmdNamePtr;
+    if (cmdNamePtr)
+        Jim_IncrRefCount(cmdNamePtr);
+    id = interp->referenceNextId++;
+    Jim_AddHashEntry(&interp->references, &id, refPtr);
+    refObjPtr = Jim_NewObj(interp);
+    refObjPtr->typePtr = &referenceObjType;
+    refObjPtr->bytes = NULL;
+    refObjPtr->internalRep.refValue.id = id;
+    refObjPtr->internalRep.refValue.refPtr = refPtr;
+    interp->referenceNextId++;
+    tag = Jim_GetString(tagPtr, &tagLen);
+    if (tagLen > JIM_REFERENCE_TAGLEN)
+        tagLen = JIM_REFERENCE_TAGLEN;
+    for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) {
+        if (i < tagLen && isrefchar(tag[i]))
+            refPtr->tag[i] = tag[i];
+        else
+            refPtr->tag[i] = '_';
+    }
+    refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0';
+    return refObjPtr;
+}
+
+Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR)
+        return NULL;
+    return objPtr->internalRep.refValue.refPtr;
+}
+
+int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr)
+{
+    Jim_Reference *refPtr;
+
+    if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
+        return JIM_ERR;
+    Jim_IncrRefCount(cmdNamePtr);
+    if (refPtr->finalizerCmdNamePtr)
+        Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr);
+    refPtr->finalizerCmdNamePtr = cmdNamePtr;
+    return JIM_OK;
+}
+
+int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr)
+{
+    Jim_Reference *refPtr;
+
+    if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL)
+        return JIM_ERR;
+    *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr;
+    return JIM_OK;
+}
+
+
+
+static const Jim_HashTableType JimRefMarkHashTableType = {
+    JimReferencesHTHashFunction,        
+    JimReferencesHTKeyDup,      
+    NULL,                       
+    JimReferencesHTKeyCompare,  
+    JimReferencesHTKeyDestructor,       
+    NULL                        
+};
+
+
+int Jim_Collect(Jim_Interp *interp)
+{
+    int collected = 0;
+    return collected;
+}
+
+#define JIM_COLLECT_ID_PERIOD 5000
+#define JIM_COLLECT_TIME_PERIOD 300
+
+void Jim_CollectIfNeeded(Jim_Interp *interp)
+{
+    unsigned long elapsedId;
+    int elapsedTime;
+
+    elapsedId = interp->referenceNextId - interp->lastCollectId;
+    elapsedTime = time(NULL) - interp->lastCollectTime;
+
+
+    if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) {
+        Jim_Collect(interp);
+    }
+}
+#endif
+
+int Jim_IsBigEndian(void)
+{
+    union {
+        unsigned short s;
+        unsigned char c[2];
+    } uval = {0x0102};
+
+    return uval.c[0] == 1;
+}
+
+
+Jim_Interp *Jim_CreateInterp(void)
+{
+    Jim_Interp *i = Jim_Alloc(sizeof(*i));
+
+    memset(i, 0, sizeof(*i));
+
+    i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH;
+    i->maxEvalDepth = JIM_MAX_EVAL_DEPTH;
+    i->lastCollectTime = time(NULL);
+
+    Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i);
+#ifdef JIM_REFERENCES
+    Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i);
+#endif
+    Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i);
+    Jim_InitHashTable(&i->packages, &JimPackageHashTableType, NULL);
+    i->emptyObj = Jim_NewEmptyStringObj(i);
+    i->trueObj = Jim_NewIntObj(i, 1);
+    i->falseObj = Jim_NewIntObj(i, 0);
+    i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL, i->emptyObj);
+    i->errorFileNameObj = i->emptyObj;
+    i->result = i->emptyObj;
+    i->stackTrace = Jim_NewListObj(i, NULL, 0);
+    i->unknown = Jim_NewStringObj(i, "unknown", -1);
+    i->errorProc = i->emptyObj;
+    i->currentScriptObj = Jim_NewEmptyStringObj(i);
+    i->nullScriptObj = Jim_NewEmptyStringObj(i);
+    Jim_IncrRefCount(i->emptyObj);
+    Jim_IncrRefCount(i->errorFileNameObj);
+    Jim_IncrRefCount(i->result);
+    Jim_IncrRefCount(i->stackTrace);
+    Jim_IncrRefCount(i->unknown);
+    Jim_IncrRefCount(i->currentScriptObj);
+    Jim_IncrRefCount(i->nullScriptObj);
+    Jim_IncrRefCount(i->errorProc);
+    Jim_IncrRefCount(i->trueObj);
+    Jim_IncrRefCount(i->falseObj);
+
+    
+    Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
+    Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
+
+    Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
+    Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
+    Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
+    Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian");
+    Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
+    Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
+    Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));
+
+    return i;
+}
+
+void Jim_FreeInterp(Jim_Interp *i)
+{
+    Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
+    Jim_Obj *objPtr, *nextObjPtr;
+
+    Jim_DecrRefCount(i, i->emptyObj);
+    Jim_DecrRefCount(i, i->trueObj);
+    Jim_DecrRefCount(i, i->falseObj);
+    Jim_DecrRefCount(i, i->result);
+    Jim_DecrRefCount(i, i->stackTrace);
+    Jim_DecrRefCount(i, i->errorProc);
+    Jim_DecrRefCount(i, i->unknown);
+    Jim_DecrRefCount(i, i->errorFileNameObj);
+    Jim_DecrRefCount(i, i->currentScriptObj);
+    Jim_DecrRefCount(i, i->nullScriptObj);
+    Jim_FreeHashTable(&i->commands);
+#ifdef JIM_REFERENCES
+    Jim_FreeHashTable(&i->references);
+#endif
+    Jim_FreeHashTable(&i->packages);
+    Jim_Free(i->prngState);
+    Jim_FreeHashTable(&i->assocData);
+
+    
+    while (cf) {
+        prevcf = cf->parent;
+        JimFreeCallFrame(i, cf, JIM_FCF_NONE);
+        cf = prevcf;
+    }
+    if (i->liveList != NULL) {
+        objPtr = i->liveList;
+
+        printf(JIM_NL "-------------------------------------" JIM_NL);
+        printf("Objects still in the free list:" JIM_NL);
+        while (objPtr) {
+            const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
+
+            if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
+                printf("%p (%d) %-10s: '%.20s...'" JIM_NL,
+                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
+            }
+            else {
+                printf("%p (%d) %-10s: '%s'" JIM_NL,
+                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
+            }
+            if (objPtr->typePtr == &sourceObjType) {
+                printf("FILE %s LINE %d" JIM_NL,
+                    Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
+                    objPtr->internalRep.sourceValue.lineNumber);
+            }
+            objPtr = objPtr->nextObjPtr;
+        }
+        printf("-------------------------------------" JIM_NL JIM_NL);
+        JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
+    }
+    
+    objPtr = i->freeList;
+    while (objPtr) {
+        nextObjPtr = objPtr->nextObjPtr;
+        Jim_Free(objPtr);
+        objPtr = nextObjPtr;
+    }
+    
+    cf = i->freeFramesList;
+    while (cf) {
+        nextcf = cf->next;
+        if (cf->vars.table != NULL)
+            Jim_Free(cf->vars.table);
+        Jim_Free(cf);
+        cf = nextcf;
+    }
+#ifdef jim_ext_load
+    Jim_FreeLoadHandles(i);
+#endif
+
+    
+    Jim_Free(i);
+}
+
+Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
+{
+    long level;
+    const char *str;
+    Jim_CallFrame *framePtr;
+
+    if (levelObjPtr) {
+        str = Jim_String(levelObjPtr);
+        if (str[0] == '#') {
+            char *endptr;
+
+            level = jim_strtol(str + 1, &endptr);
+            if (str[1] == '\0' || endptr[0] != '\0') {
+                level = -1;
+            }
+        }
+        else {
+            if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) {
+                level = -1;
+            }
+            else {
+                
+                level = interp->framePtr->level - level;
+            }
+        }
+    }
+    else {
+        str = "1";              
+        level = interp->framePtr->level - 1;
+    }
+
+    if (level == 0) {
+        return interp->topFramePtr;
+    }
+    if (level > 0) {
+        
+        for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
+            if (framePtr->level == level) {
+                return framePtr;
+            }
+        }
+    }
+
+    Jim_SetResultFormatted(interp, "bad level \"%s\"", str);
+    return NULL;
+}
+
+static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr)
+{
+    long level;
+    Jim_CallFrame *framePtr;
+
+    if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
+        if (level <= 0) {
+            
+            level = interp->framePtr->level + level;
+        }
+
+        if (level == 0) {
+            return interp->topFramePtr;
+        }
+
+        
+        for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
+            if (framePtr->level == level) {
+                return framePtr;
+            }
+        }
+    }
+
+    Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
+    return NULL;
+}
+
+static void JimResetStackTrace(Jim_Interp *interp)
+{
+    Jim_DecrRefCount(interp, interp->stackTrace);
+    interp->stackTrace = Jim_NewListObj(interp, NULL, 0);
+    Jim_IncrRefCount(interp->stackTrace);
+}
+
+static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
+{
+    int len;
+
+    
+    Jim_IncrRefCount(stackTraceObj);
+    Jim_DecrRefCount(interp, interp->stackTrace);
+    interp->stackTrace = stackTraceObj;
+    interp->errorFlag = 1;
+
+    len = Jim_ListLength(interp, interp->stackTrace);
+    if (len >= 3) {
+        if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) {
+            interp->addStackTrace = 1;
+        }
+    }
+}
+
+
+static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
+    Jim_Obj *fileNameObj, int linenr)
+{
+    if (strcmp(procname, "unknown") == 0) {
+        procname = "";
+    }
+    if (!*procname && !Jim_Length(fileNameObj)) {
+        
+        return;
+    }
+
+    if (Jim_IsShared(interp->stackTrace)) {
+        Jim_DecrRefCount(interp, interp->stackTrace);
+        interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
+        Jim_IncrRefCount(interp->stackTrace);
+    }
+
+    
+    if (!*procname && Jim_Length(fileNameObj)) {
+        
+        int len = Jim_ListLength(interp, interp->stackTrace);
+
+        if (len >= 3) {
+            Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
+            if (Jim_Length(objPtr)) {
+                
+                objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
+                if (Jim_Length(objPtr) == 0) {
+                    
+                    ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
+                    ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
+                    return;
+                }
+            }
+        }
+    }
+
+    Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1));
+    Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj);
+    Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr));
+}
+
+int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc,
+    void *data)
+{
+    AssocDataValue *assocEntryPtr = (AssocDataValue *) Jim_Alloc(sizeof(AssocDataValue));
+
+    assocEntryPtr->delProc = delProc;
+    assocEntryPtr->data = data;
+    return Jim_AddHashEntry(&interp->assocData, key, assocEntryPtr);
+}
+
+void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
+{
+    Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
+
+    if (entryPtr != NULL) {
+        AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
+
+        return assocEntryPtr->data;
+    }
+    return NULL;
+}
+
+int Jim_DeleteAssocData(Jim_Interp *interp, const char *key)
+{
+    return Jim_DeleteHashEntry(&interp->assocData, key);
+}
+
+int Jim_GetExitCode(Jim_Interp *interp)
+{
+    return interp->exitCode;
+}
+
+static void UpdateStringOfInt(struct Jim_Obj *objPtr);
+static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
+
+static const Jim_ObjType intObjType = {
+    "int",
+    NULL,
+    NULL,
+    UpdateStringOfInt,
+    JIM_TYPE_NONE,
+};
+
+static const Jim_ObjType coercedDoubleObjType = {
+    "coerced-double",
+    NULL,
+    NULL,
+    UpdateStringOfInt,
+    JIM_TYPE_NONE,
+};
+
+
+static void UpdateStringOfInt(struct Jim_Obj *objPtr)
+{
+    int len;
+    char buf[JIM_INTEGER_SPACE + 1];
+
+    len = JimWideToString(buf, JimWideValue(objPtr));
+    objPtr->bytes = Jim_Alloc(len + 1);
+    memcpy(objPtr->bytes, buf, len + 1);
+    objPtr->length = len;
+}
+
+int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
+{
+    jim_wide wideValue;
+    const char *str;
+
+    if (objPtr->typePtr == &coercedDoubleObjType) {
+        
+        objPtr->typePtr = &intObjType;
+        return JIM_OK;
+    }
+
+    
+    str = Jim_String(objPtr);
+    
+    if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) {
+        if (flags & JIM_ERRMSG) {
+            Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr);
+        }
+        return JIM_ERR;
+    }
+    if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) {
+        Jim_SetResultString(interp, "Integer value too big to be represented", -1);
+        return JIM_ERR;
+    }
+    
+    Jim_FreeIntRep(interp, objPtr);
+    objPtr->typePtr = &intObjType;
+    objPtr->internalRep.wideValue = wideValue;
+    return JIM_OK;
+}
+
+#ifdef JIM_OPTIMIZATION
+static int JimIsWide(Jim_Obj *objPtr)
+{
+    return objPtr->typePtr == &intObjType;
+}
+#endif
+
+int Jim_GetWide(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr)
+{
+    if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR)
+        return JIM_ERR;
+    *widePtr = JimWideValue(objPtr);
+    return JIM_OK;
+}
+
+
+static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr)
+{
+    if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_NONE) == JIM_ERR)
+        return JIM_ERR;
+    *widePtr = JimWideValue(objPtr);
+    return JIM_OK;
+}
+
+int Jim_GetLong(Jim_Interp *interp, Jim_Obj *objPtr, long *longPtr)
+{
+    jim_wide wideValue;
+    int retval;
+
+    retval = Jim_GetWide(interp, objPtr, &wideValue);
+    if (retval == JIM_OK) {
+        *longPtr = (long)wideValue;
+        return JIM_OK;
+    }
+    return JIM_ERR;
+}
+
+Jim_Obj *Jim_NewIntObj(Jim_Interp *interp, jim_wide wideValue)
+{
+    Jim_Obj *objPtr;
+
+    objPtr = Jim_NewObj(interp);
+    objPtr->typePtr = &intObjType;
+    objPtr->bytes = NULL;
+    objPtr->internalRep.wideValue = wideValue;
+    return objPtr;
+}
+
+#define JIM_DOUBLE_SPACE 30
+
+static void UpdateStringOfDouble(struct Jim_Obj *objPtr);
+static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
+
+static const Jim_ObjType doubleObjType = {
+    "double",
+    NULL,
+    NULL,
+    UpdateStringOfDouble,
+    JIM_TYPE_NONE,
+};
+
+void UpdateStringOfDouble(struct Jim_Obj *objPtr)
+{
+    int len;
+    char buf[JIM_DOUBLE_SPACE + 1];
+
+    len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
+    objPtr->bytes = Jim_Alloc(len + 1);
+    memcpy(objPtr->bytes, buf, len + 1);
+    objPtr->length = len;
+}
+
+int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    double doubleValue;
+    jim_wide wideValue;
+    const char *str;
+
+    str = Jim_String(objPtr);
+
+#ifdef HAVE_LONG_LONG
+    
+#define MIN_INT_IN_DOUBLE -(1LL << 53)
+#define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1)
+
+    if (objPtr->typePtr == &intObjType
+        && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE
+        && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) {
+
+        
+        objPtr->typePtr = &coercedDoubleObjType;
+        return JIM_OK;
+    }
+    else
+#endif
+    if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) {
+        
+        Jim_FreeIntRep(interp, objPtr);
+        objPtr->typePtr = &coercedDoubleObjType;
+        objPtr->internalRep.wideValue = wideValue;
+        return JIM_OK;
+    }
+    else {
+        
+        if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) {
+            Jim_SetResultFormatted(interp, "expected number but got \"%#s\"", objPtr);
+            return JIM_ERR;
+        }
+        
+        Jim_FreeIntRep(interp, objPtr);
+    }
+    objPtr->typePtr = &doubleObjType;
+    objPtr->internalRep.doubleValue = doubleValue;
+    return JIM_OK;
+}
+
+int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, double *doublePtr)
+{
+    if (objPtr->typePtr == &coercedDoubleObjType) {
+        *doublePtr = JimWideValue(objPtr);
+        return JIM_OK;
+    }
+    if (objPtr->typePtr != &doubleObjType && SetDoubleFromAny(interp, objPtr) == JIM_ERR)
+        return JIM_ERR;
+
+    if (objPtr->typePtr == &coercedDoubleObjType) {
+        *doublePtr = JimWideValue(objPtr);
+    }
+    else {
+        *doublePtr = objPtr->internalRep.doubleValue;
+    }
+    return JIM_OK;
+}
+
+Jim_Obj *Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue)
+{
+    Jim_Obj *objPtr;
+
+    objPtr = Jim_NewObj(interp);
+    objPtr->typePtr = &doubleObjType;
+    objPtr->bytes = NULL;
+    objPtr->internalRep.doubleValue = doubleValue;
+    return objPtr;
+}
+
+static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
+static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
+static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+static void UpdateStringOfList(struct Jim_Obj *objPtr);
+static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+
+static const Jim_ObjType listObjType = {
+    "list",
+    FreeListInternalRep,
+    DupListInternalRep,
+    UpdateStringOfList,
+    JIM_TYPE_NONE,
+};
+
+void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    int i;
+
+    for (i = 0; i < objPtr->internalRep.listValue.len; i++) {
+        Jim_DecrRefCount(interp, objPtr->internalRep.listValue.ele[i]);
+    }
+    Jim_Free(objPtr->internalRep.listValue.ele);
+}
+
+void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    int i;
+
+    JIM_NOTUSED(interp);
+
+    dupPtr->internalRep.listValue.len = srcPtr->internalRep.listValue.len;
+    dupPtr->internalRep.listValue.maxLen = srcPtr->internalRep.listValue.maxLen;
+    dupPtr->internalRep.listValue.ele =
+        Jim_Alloc(sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.maxLen);
+    memcpy(dupPtr->internalRep.listValue.ele, srcPtr->internalRep.listValue.ele,
+        sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.len);
+    for (i = 0; i < dupPtr->internalRep.listValue.len; i++) {
+        Jim_IncrRefCount(dupPtr->internalRep.listValue.ele[i]);
+    }
+    dupPtr->typePtr = &listObjType;
+}
+
+#define JIM_ELESTR_SIMPLE 0
+#define JIM_ELESTR_BRACE 1
+#define JIM_ELESTR_QUOTE 2
+static unsigned char ListElementQuotingType(const char *s, int len)
+{
+    int i, level, blevel, trySimple = 1;
+
+    
+    if (len == 0)
+        return JIM_ELESTR_BRACE;
+    if (s[0] == '"' || s[0] == '{') {
+        trySimple = 0;
+        goto testbrace;
+    }
+    for (i = 0; i < len; i++) {
+        switch (s[i]) {
+            case ' ':
+            case '$':
+            case '"':
+            case '[':
+            case ']':
+            case ';':
+            case '\\':
+            case '\r':
+            case '\n':
+            case '\t':
+            case '\f':
+            case '\v':
+                trySimple = 0;
+            case '{':
+            case '}':
+                goto testbrace;
+        }
+    }
+    return JIM_ELESTR_SIMPLE;
+
+  testbrace:
+    
+    if (s[len - 1] == '\\')
+        return JIM_ELESTR_QUOTE;
+    level = 0;
+    blevel = 0;
+    for (i = 0; i < len; i++) {
+        switch (s[i]) {
+            case '{':
+                level++;
+                break;
+            case '}':
+                level--;
+                if (level < 0)
+                    return JIM_ELESTR_QUOTE;
+                break;
+            case '[':
+                blevel++;
+                break;
+            case ']':
+                blevel--;
+                break;
+            case '\\':
+                if (s[i + 1] == '\n')
+                    return JIM_ELESTR_QUOTE;
+                else if (s[i + 1] != '\0')
+                    i++;
+                break;
+        }
+    }
+    if (blevel < 0) {
+        return JIM_ELESTR_QUOTE;
+    }
+
+    if (level == 0) {
+        if (!trySimple)
+            return JIM_ELESTR_BRACE;
+        for (i = 0; i < len; i++) {
+            switch (s[i]) {
+                case ' ':
+                case '$':
+                case '"':
+                case '[':
+                case ']':
+                case ';':
+                case '\\':
+                case '\r':
+                case '\n':
+                case '\t':
+                case '\f':
+                case '\v':
+                    return JIM_ELESTR_BRACE;
+                    break;
+            }
+        }
+        return JIM_ELESTR_SIMPLE;
+    }
+    return JIM_ELESTR_QUOTE;
+}
+
+static int BackslashQuoteString(const char *s, char *q)
+{
+    char *p = q;
+
+    while (*s) {
+        switch (*s) {
+            case ' ':
+            case '$':
+            case '"':
+            case '[':
+            case ']':
+            case '{':
+            case '}':
+            case ';':
+            case '\\':
+                *p++ = '\\';
+                *p++ = *s++;
+                break;
+            case '\n':
+                *p++ = '\\';
+                *p++ = 'n';
+                s++;
+                break;
+            case '\r':
+                *p++ = '\\';
+                *p++ = 'r';
+                s++;
+                break;
+            case '\t':
+                *p++ = '\\';
+                *p++ = 't';
+                s++;
+                break;
+            case '\f':
+                *p++ = '\\';
+                *p++ = 'f';
+                s++;
+                break;
+            case '\v':
+                *p++ = '\\';
+                *p++ = 'v';
+                s++;
+                break;
+            default:
+                *p++ = *s++;
+                break;
+        }
+    }
+    *p = '\0';
+
+    return p - q;
+}
+
+static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
+{
+    #define STATIC_QUOTING_LEN 32
+    int i, bufLen, realLength;
+    const char *strRep;
+    char *p;
+    unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
+
+    
+    if (objc > STATIC_QUOTING_LEN) {
+        quotingType = Jim_Alloc(objc);
+    }
+    else {
+        quotingType = staticQuoting;
+    }
+    bufLen = 0;
+    for (i = 0; i < objc; i++) {
+        int len;
+
+        strRep = Jim_GetString(objv[i], &len);
+        quotingType[i] = ListElementQuotingType(strRep, len);
+        switch (quotingType[i]) {
+            case JIM_ELESTR_SIMPLE:
+                if (i != 0 || strRep[0] != '#') {
+                    bufLen += len;
+                    break;
+                }
+                
+                quotingType[i] = JIM_ELESTR_BRACE;
+                
+            case JIM_ELESTR_BRACE:
+                bufLen += len + 2;
+                break;
+            case JIM_ELESTR_QUOTE:
+                bufLen += len * 2;
+                break;
+        }
+        bufLen++;               
+    }
+    bufLen++;
+
+    
+    p = objPtr->bytes = Jim_Alloc(bufLen + 1);
+    realLength = 0;
+    for (i = 0; i < objc; i++) {
+        int len, qlen;
+
+        strRep = Jim_GetString(objv[i], &len);
+
+        switch (quotingType[i]) {
+            case JIM_ELESTR_SIMPLE:
+                memcpy(p, strRep, len);
+                p += len;
+                realLength += len;
+                break;
+            case JIM_ELESTR_BRACE:
+                *p++ = '{';
+                memcpy(p, strRep, len);
+                p += len;
+                *p++ = '}';
+                realLength += len + 2;
+                break;
+            case JIM_ELESTR_QUOTE:
+                if (i == 0 && strRep[0] == '#') {
+                    *p++ = '\\';
+                    realLength++;
+                }
+                qlen = BackslashQuoteString(strRep, p);
+                p += qlen;
+                realLength += qlen;
+                break;
+        }
+        
+        if (i + 1 != objc) {
+            *p++ = ' ';
+            realLength++;
+        }
+    }
+    *p = '\0';                  
+    objPtr->length = realLength;
+
+    if (quotingType != staticQuoting) {
+        Jim_Free(quotingType);
+    }
+}
+
+static void UpdateStringOfList(struct Jim_Obj *objPtr)
+{
+    JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
+}
+
+static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
+{
+    struct JimParserCtx parser;
+    const char *str;
+    int strLen;
+    Jim_Obj *fileNameObj;
+    int linenr;
+
+    if (objPtr->typePtr == &listObjType) {
+        return JIM_OK;
+    }
+
+    if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
+        Jim_Obj **listObjPtrPtr;
+        int len;
+        int i;
+
+        listObjPtrPtr = JimDictPairs(objPtr, &len);
+        for (i = 0; i < len; i++) {
+            Jim_IncrRefCount(listObjPtrPtr[i]);
+        }
+
+        
+        Jim_FreeIntRep(interp, objPtr);
+        objPtr->typePtr = &listObjType;
+        objPtr->internalRep.listValue.len = len;
+        objPtr->internalRep.listValue.maxLen = len;
+        objPtr->internalRep.listValue.ele = listObjPtrPtr;
+
+        return JIM_OK;
+    }
+
+    
+    if (objPtr->typePtr == &sourceObjType) {
+        fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
+        linenr = objPtr->internalRep.sourceValue.lineNumber;
+    }
+    else {
+        fileNameObj = interp->emptyObj;
+        linenr = 1;
+    }
+    Jim_IncrRefCount(fileNameObj);
+
+    
+    str = Jim_GetString(objPtr, &strLen);
+
+    Jim_FreeIntRep(interp, objPtr);
+    objPtr->typePtr = &listObjType;
+    objPtr->internalRep.listValue.len = 0;
+    objPtr->internalRep.listValue.maxLen = 0;
+    objPtr->internalRep.listValue.ele = NULL;
+
+    
+    if (strLen) {
+        JimParserInit(&parser, str, strLen, linenr);
+        while (!parser.eof) {
+            Jim_Obj *elementPtr;
+
+            JimParseList(&parser);
+            if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC)
+                continue;
+            elementPtr = JimParserGetTokenObj(interp, &parser);
+            JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline);
+            ListAppendElement(objPtr, elementPtr);
+        }
+    }
+    Jim_DecrRefCount(interp, fileNameObj);
+    return JIM_OK;
+}
+
+Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
+{
+    Jim_Obj *objPtr;
+
+    objPtr = Jim_NewObj(interp);
+    objPtr->typePtr = &listObjType;
+    objPtr->bytes = NULL;
+    objPtr->internalRep.listValue.ele = NULL;
+    objPtr->internalRep.listValue.len = 0;
+    objPtr->internalRep.listValue.maxLen = 0;
+
+    if (len) {
+        ListInsertElements(objPtr, 0, len, elements);
+    }
+
+    return objPtr;
+}
+
+static void JimListGetElements(Jim_Interp *interp, Jim_Obj *listObj, int *listLen,
+    Jim_Obj ***listVec)
+{
+    *listLen = Jim_ListLength(interp, listObj);
+    *listVec = listObj->internalRep.listValue.ele;
+}
+
+
+static int JimSign(jim_wide w)
+{
+    if (w == 0) {
+        return 0;
+    }
+    else if (w < 0) {
+        return -1;
+    }
+    return 1;
+}
+
+
+struct lsort_info {
+    jmp_buf jmpbuf;
+    Jim_Obj *command;
+    Jim_Interp *interp;
+    enum {
+        JIM_LSORT_ASCII,
+        JIM_LSORT_NOCASE,
+        JIM_LSORT_INTEGER,
+        JIM_LSORT_COMMAND
+    } type;
+    int order;
+    int index;
+    int indexed;
+    int (*subfn)(Jim_Obj **, Jim_Obj **);
+};
+
+static struct lsort_info *sort_info;
+
+static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
+{
+    Jim_Obj *lObj, *rObj;
+
+    if (Jim_ListIndex(sort_info->interp, *lhsObj, sort_info->index, &lObj, JIM_ERRMSG) != JIM_OK ||
+        Jim_ListIndex(sort_info->interp, *rhsObj, sort_info->index, &rObj, JIM_ERRMSG) != JIM_OK) {
+        longjmp(sort_info->jmpbuf, JIM_ERR);
+    }
+    return sort_info->subfn(&lObj, &rObj);
+}
+
+
+static int ListSortString(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
+{
+    return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order;
+}
+
+static int ListSortStringNoCase(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
+{
+    return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 1) * sort_info->order;
+}
+
+static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
+{
+    jim_wide lhs = 0, rhs = 0;
+
+    if (Jim_GetWide(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
+        Jim_GetWide(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
+        longjmp(sort_info->jmpbuf, JIM_ERR);
+    }
+
+    return JimSign(lhs - rhs) * sort_info->order;
+}
+
+static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
+{
+    Jim_Obj *compare_script;
+    int rc;
+
+    jim_wide ret = 0;
+
+    
+    compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command);
+    Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj);
+    Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj);
+
+    rc = Jim_EvalObj(sort_info->interp, compare_script);
+
+    if (rc != JIM_OK || Jim_GetWide(sort_info->interp, Jim_GetResult(sort_info->interp), &ret) != JIM_OK) {
+        longjmp(sort_info->jmpbuf, rc);
+    }
+
+    return JimSign(ret) * sort_info->order;
+}
+
+
+static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
+{
+    struct lsort_info *prev_info;
+
+    typedef int (qsort_comparator) (const void *, const void *);
+    int (*fn) (Jim_Obj **, Jim_Obj **);
+    Jim_Obj **vector;
+    int len;
+    int rc;
+
+    JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
+    SetListFromAny(interp, listObjPtr);
+
+    
+    prev_info = sort_info;
+    sort_info = info;
+
+    vector = listObjPtr->internalRep.listValue.ele;
+    len = listObjPtr->internalRep.listValue.len;
+    switch (info->type) {
+        case JIM_LSORT_ASCII:
+            fn = ListSortString;
+            break;
+        case JIM_LSORT_NOCASE:
+            fn = ListSortStringNoCase;
+            break;
+        case JIM_LSORT_INTEGER:
+            fn = ListSortInteger;
+            break;
+        case JIM_LSORT_COMMAND:
+            fn = ListSortCommand;
+            break;
+        default:
+            fn = NULL;          
+            JimPanic((1, "ListSort called with invalid sort type"));
+    }
+
+    if (info->indexed) {
+        
+        info->subfn = fn;
+        fn = ListSortIndexHelper;
+    }
+
+    if ((rc = setjmp(info->jmpbuf)) == 0) {
+        qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
+    }
+    Jim_InvalidateStringRep(listObjPtr);
+    sort_info = prev_info;
+
+    return rc;
+}
+
+static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec)
+{
+    int currentLen = listPtr->internalRep.listValue.len;
+    int requiredLen = currentLen + elemc;
+    int i;
+    Jim_Obj **point;
+
+    if (requiredLen > listPtr->internalRep.listValue.maxLen) {
+        if (requiredLen < 2) {
+            
+            requiredLen = 4;
+        }
+        else {
+            requiredLen *= 2;
+        }
+
+        listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
+            sizeof(Jim_Obj *) * requiredLen);
+
+        listPtr->internalRep.listValue.maxLen = requiredLen;
+    }
+    if (idx < 0) {
+        idx = currentLen;
+    }
+    point = listPtr->internalRep.listValue.ele + idx;
+    memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *));
+    for (i = 0; i < elemc; ++i) {
+        point[i] = elemVec[i];
+        Jim_IncrRefCount(point[i]);
+    }
+    listPtr->internalRep.listValue.len += elemc;
+}
+
+static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr)
+{
+    ListInsertElements(listPtr, -1, 1, &objPtr);
+}
+
+static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr)
+{
+    ListInsertElements(listPtr, -1,
+        appendListPtr->internalRep.listValue.len, appendListPtr->internalRep.listValue.ele);
+}
+
+void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr)
+{
+    JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendElement called with shared object"));
+    SetListFromAny(interp, listPtr);
+    Jim_InvalidateStringRep(listPtr);
+    ListAppendElement(listPtr, objPtr);
+}
+
+void Jim_ListAppendList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr)
+{
+    JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendList called with shared object"));
+    SetListFromAny(interp, listPtr);
+    SetListFromAny(interp, appendListPtr);
+    Jim_InvalidateStringRep(listPtr);
+    ListAppendList(listPtr, appendListPtr);
+}
+
+int Jim_ListLength(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    SetListFromAny(interp, objPtr);
+    return objPtr->internalRep.listValue.len;
+}
+
+void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
+    int objc, Jim_Obj *const *objVec)
+{
+    JimPanic((Jim_IsShared(listPtr), "Jim_ListInsertElement called with shared object"));
+    SetListFromAny(interp, listPtr);
+    if (idx >= 0 && idx > listPtr->internalRep.listValue.len)
+        idx = listPtr->internalRep.listValue.len;
+    else if (idx < 0)
+        idx = 0;
+    Jim_InvalidateStringRep(listPtr);
+    ListInsertElements(listPtr, idx, objc, objVec);
+}
+
+Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx)
+{
+    SetListFromAny(interp, listPtr);
+    if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) ||
+        (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) {
+        return NULL;
+    }
+    if (idx < 0)
+        idx = listPtr->internalRep.listValue.len + idx;
+    return listPtr->internalRep.listValue.ele[idx];
+}
+
+int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPtrPtr, int flags)
+{
+    *objPtrPtr = Jim_ListGetIndex(interp, listPtr, idx);
+    if (*objPtrPtr == NULL) {
+        if (flags & JIM_ERRMSG) {
+            Jim_SetResultString(interp, "list index out of range", -1);
+        }
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
+    Jim_Obj *newObjPtr, int flags)
+{
+    SetListFromAny(interp, listPtr);
+    if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) ||
+        (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) {
+        if (flags & JIM_ERRMSG) {
+            Jim_SetResultString(interp, "list index out of range", -1);
+        }
+        return JIM_ERR;
+    }
+    if (idx < 0)
+        idx = listPtr->internalRep.listValue.len + idx;
+    Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]);
+    listPtr->internalRep.listValue.ele[idx] = newObjPtr;
+    Jim_IncrRefCount(newObjPtr);
+    return JIM_OK;
+}
+
+int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
+    Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
+{
+    Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
+    int shared, i, idx;
+
+    varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG | JIM_UNSHARED);
+    if (objPtr == NULL)
+        return JIM_ERR;
+    if ((shared = Jim_IsShared(objPtr)))
+        varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
+    for (i = 0; i < indexc - 1; i++) {
+        listObjPtr = objPtr;
+        if (Jim_GetIndex(interp, indexv[i], &idx) != JIM_OK)
+            goto err;
+        if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_ERRMSG) != JIM_OK) {
+            goto err;
+        }
+        if (Jim_IsShared(objPtr)) {
+            objPtr = Jim_DuplicateObj(interp, objPtr);
+            ListSetIndex(interp, listObjPtr, idx, objPtr, JIM_NONE);
+        }
+        Jim_InvalidateStringRep(listObjPtr);
+    }
+    if (Jim_GetIndex(interp, indexv[indexc - 1], &idx) != JIM_OK)
+        goto err;
+    if (ListSetIndex(interp, objPtr, idx, newObjPtr, JIM_ERRMSG) == JIM_ERR)
+        goto err;
+    Jim_InvalidateStringRep(objPtr);
+    Jim_InvalidateStringRep(varObjPtr);
+    if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK)
+        goto err;
+    Jim_SetResult(interp, varObjPtr);
+    return JIM_OK;
+  err:
+    if (shared) {
+        Jim_FreeNewObj(interp, varObjPtr);
+    }
+    return JIM_ERR;
+}
+
+Jim_Obj *Jim_ListJoin(Jim_Interp *interp, Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen)
+{
+    int i;
+    int listLen = Jim_ListLength(interp, listObjPtr);
+    Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
+
+    for (i = 0; i < listLen; ) {
+        Jim_Obj *objPtr;
+
+        Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
+        Jim_AppendObj(interp, resObjPtr, objPtr);
+        if (++i != listLen) {
+            Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
+        }
+    }
+    return resObjPtr;
+}
+
+Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
+{
+    int i;
+
+    for (i = 0; i < objc; i++) {
+        if (!Jim_IsList(objv[i]))
+            break;
+    }
+    if (i == objc) {
+        Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
+
+        for (i = 0; i < objc; i++)
+            ListAppendList(objPtr, objv[i]);
+        return objPtr;
+    }
+    else {
+        
+        int len = 0, objLen;
+        char *bytes, *p;
+
+        
+        for (i = 0; i < objc; i++) {
+            Jim_GetString(objv[i], &objLen);
+            len += objLen;
+        }
+        if (objc)
+            len += objc - 1;
+        
+        p = bytes = Jim_Alloc(len + 1);
+        for (i = 0; i < objc; i++) {
+            const char *s = Jim_GetString(objv[i], &objLen);
+
+            
+            while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
+                s++;
+                objLen--;
+                len--;
+            }
+            
+            while (objLen && (s[objLen - 1] == ' ' ||
+                    s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
+                
+                if (objLen > 1 && s[objLen - 2] == '\\') {
+                    break;
+                }
+                objLen--;
+                len--;
+            }
+            memcpy(p, s, objLen);
+            p += objLen;
+            if (objLen && i + 1 != objc) {
+                *p++ = ' ';
+            }
+            else if (i + 1 != objc) {
+                len--;
+            }
+        }
+        *p = '\0';
+        return Jim_NewStringObjNoAlloc(interp, bytes, len);
+    }
+}
+
+Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstObjPtr,
+    Jim_Obj *lastObjPtr)
+{
+    int first, last;
+    int len, rangeLen;
+
+    if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
+        Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
+        return NULL;
+    len = Jim_ListLength(interp, listObjPtr);   
+    first = JimRelToAbsIndex(len, first);
+    last = JimRelToAbsIndex(len, last);
+    JimRelToAbsRange(len, &first, &last, &rangeLen);
+    if (first == 0 && last == len) {
+        return listObjPtr;
+    }
+    return Jim_NewListObj(interp, listObjPtr->internalRep.listValue.ele + first, rangeLen);
+}
+
+static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+static void UpdateStringOfDict(struct Jim_Obj *objPtr);
+static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+
+
+static unsigned int JimObjectHTHashFunction(const void *key)
+{
+    int len;
+    const char *str = Jim_GetString((Jim_Obj *)key, &len);
+    return Jim_GenHashFunction((const unsigned char *)str, len);
+}
+
+static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
+{
+    return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
+}
+
+static void JimObjectHTKeyValDestructor(void *interp, void *val)
+{
+    Jim_DecrRefCount(interp, (Jim_Obj *)val);
+}
+
+static const Jim_HashTableType JimDictHashTableType = {
+    JimObjectHTHashFunction,    
+    NULL,                       
+    NULL,                       
+    JimObjectHTKeyCompare,      
+    JimObjectHTKeyValDestructor,    
+    JimObjectHTKeyValDestructor 
+};
+
+static const Jim_ObjType dictObjType = {
+    "dict",
+    FreeDictInternalRep,
+    DupDictInternalRep,
+    UpdateStringOfDict,
+    JIM_TYPE_NONE,
+};
+
+void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    JIM_NOTUSED(interp);
+
+    Jim_FreeHashTable(objPtr->internalRep.ptr);
+    Jim_Free(objPtr->internalRep.ptr);
+}
+
+void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    Jim_HashTable *ht, *dupHt;
+    Jim_HashTableIterator htiter;
+    Jim_HashEntry *he;
+
+    
+    ht = srcPtr->internalRep.ptr;
+    dupHt = Jim_Alloc(sizeof(*dupHt));
+    Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
+    if (ht->size != 0)
+        Jim_ExpandHashTable(dupHt, ht->size);
+    
+    JimInitHashTableIterator(ht, &htiter);
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        const Jim_Obj *keyObjPtr = he->key;
+        Jim_Obj *valObjPtr = he->u.val;
+
+        Jim_IncrRefCount((Jim_Obj *)keyObjPtr); 
+        Jim_IncrRefCount(valObjPtr);
+        Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
+    }
+
+    dupPtr->internalRep.ptr = dupHt;
+    dupPtr->typePtr = &dictObjType;
+}
+
+static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
+{
+    Jim_HashTable *ht;
+    Jim_HashTableIterator htiter;
+    Jim_HashEntry *he;
+    Jim_Obj **objv;
+    int i;
+
+    ht = dictPtr->internalRep.ptr;
+
+    
+    objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
+    JimInitHashTableIterator(ht, &htiter);
+    i = 0;
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        objv[i++] = (Jim_Obj *)he->key;
+        objv[i++] = he->u.val;
+    }
+    *len = i;
+    return objv;
+}
+
+static void UpdateStringOfDict(struct Jim_Obj *objPtr)
+{
+    
+    int len;
+    Jim_Obj **objv = JimDictPairs(objPtr, &len);
+
+    JimMakeListStringRep(objPtr, objv, len);
+
+    Jim_Free(objv);
+}
+
+static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
+{
+    int listlen;
+
+    if (objPtr->typePtr == &dictObjType) {
+        return JIM_OK;
+    }
+
+    Jim_String(objPtr);
+
+    
+    listlen = Jim_ListLength(interp, objPtr);
+    if (listlen % 2) {
+        Jim_SetResultString(interp, "missing value to go with key", -1);
+        return JIM_ERR;
+    }
+    else {
+        
+        Jim_HashTable *ht;
+        int i;
+
+        ht = Jim_Alloc(sizeof(*ht));
+        Jim_InitHashTable(ht, &JimDictHashTableType, interp);
+
+        for (i = 0; i < listlen; i += 2) {
+            Jim_Obj *keyObjPtr;
+            Jim_Obj *valObjPtr;
+
+            Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
+            Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
+
+            Jim_IncrRefCount(keyObjPtr);
+            Jim_IncrRefCount(valObjPtr);
+
+            if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
+                Jim_HashEntry *he;
+
+                he = Jim_FindHashEntry(ht, keyObjPtr);
+                Jim_DecrRefCount(interp, keyObjPtr);
+                
+                Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
+                he->u.val = valObjPtr;
+            }
+        }
+
+        Jim_FreeIntRep(interp, objPtr);
+        objPtr->typePtr = &dictObjType;
+        objPtr->internalRep.ptr = ht;
+
+        return JIM_OK;
+    }
+}
+
+
+
+static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
+    Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
+{
+    Jim_HashTable *ht = objPtr->internalRep.ptr;
+
+    if (valueObjPtr == NULL) {  
+        return Jim_DeleteHashEntry(ht, keyObjPtr);
+    }
+    Jim_IncrRefCount(keyObjPtr);
+    Jim_IncrRefCount(valueObjPtr);
+    if (Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr)) {
+        
+        Jim_DecrRefCount(interp, keyObjPtr);
+    }
+    return JIM_OK;
+}
+
+int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
+    Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
+{
+    int retcode;
+
+    JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+    retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
+    Jim_InvalidateStringRep(objPtr);
+    return retcode;
+}
+
+Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
+{
+    Jim_Obj *objPtr;
+    int i;
+
+    JimPanic((len % 2, "Jim_NewDictObj() 'len' argument must be even"));
+
+    objPtr = Jim_NewObj(interp);
+    objPtr->typePtr = &dictObjType;
+    objPtr->bytes = NULL;
+    objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable));
+    Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp);
+    for (i = 0; i < len; i += 2)
+        DictAddElement(interp, objPtr, elements[i], elements[i + 1]);
+    return objPtr;
+}
+
+int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
+    Jim_Obj **objPtrPtr, int flags)
+{
+    Jim_HashEntry *he;
+    Jim_HashTable *ht;
+
+    if (SetDictFromAny(interp, dictPtr) != JIM_OK) {
+        return -1;
+    }
+    ht = dictPtr->internalRep.ptr;
+    if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) {
+        if (flags & JIM_ERRMSG) {
+            Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
+        }
+        return JIM_ERR;
+    }
+    *objPtrPtr = he->u.val;
+    return JIM_OK;
+}
+
+
+int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
+{
+    if (SetDictFromAny(interp, dictPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+    *objPtrPtr = JimDictPairs(dictPtr, len);
+
+    return JIM_OK;
+}
+
+
+
+int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr,
+    Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags)
+{
+    int i;
+
+    if (keyc == 0) {
+        *objPtrPtr = dictPtr;
+        return JIM_OK;
+    }
+
+    for (i = 0; i < keyc; i++) {
+        Jim_Obj *objPtr;
+
+        int rc = Jim_DictKey(interp, dictPtr, keyv[i], &objPtr, flags);
+        if (rc != JIM_OK) {
+            return rc;
+        }
+        dictPtr = objPtr;
+    }
+    *objPtrPtr = dictPtr;
+    return JIM_OK;
+}
+
+int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
+    Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr, int flags)
+{
+    Jim_Obj *varObjPtr, *objPtr, *dictObjPtr;
+    int shared, i;
+
+    varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
+    if (objPtr == NULL) {
+        if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
+            
+            return JIM_ERR;
+        }
+        varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
+        if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
+            Jim_FreeNewObj(interp, varObjPtr);
+            return JIM_ERR;
+        }
+    }
+    if ((shared = Jim_IsShared(objPtr)))
+        varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
+    for (i = 0; i < keyc; i++) {
+        dictObjPtr = objPtr;
+
+        
+        if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
+            goto err;
+        }
+
+        if (i == keyc - 1) {
+            
+            if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
+                if (newObjPtr || (flags & JIM_MUSTEXIST)) {
+                    goto err;
+                }
+            }
+            break;
+        }
+
+        
+        Jim_InvalidateStringRep(dictObjPtr);
+        if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
+                newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) {
+            if (Jim_IsShared(objPtr)) {
+                objPtr = Jim_DuplicateObj(interp, objPtr);
+                DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
+            }
+        }
+        else {
+            if (newObjPtr == NULL) {
+                goto err;
+            }
+            objPtr = Jim_NewDictObj(interp, NULL, 0);
+            DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
+        }
+    }
+    Jim_InvalidateStringRep(objPtr);
+    Jim_InvalidateStringRep(varObjPtr);
+    if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
+        goto err;
+    }
+    Jim_SetResult(interp, varObjPtr);
+    return JIM_OK;
+  err:
+    if (shared) {
+        Jim_FreeNewObj(interp, varObjPtr);
+    }
+    return JIM_ERR;
+}
+
+static void UpdateStringOfIndex(struct Jim_Obj *objPtr);
+static int SetIndexFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+
+static const Jim_ObjType indexObjType = {
+    "index",
+    NULL,
+    NULL,
+    UpdateStringOfIndex,
+    JIM_TYPE_NONE,
+};
+
+void UpdateStringOfIndex(struct Jim_Obj *objPtr)
+{
+    int len;
+    char buf[JIM_INTEGER_SPACE + 1];
+
+    if (objPtr->internalRep.intValue >= 0)
+        len = sprintf(buf, "%d", objPtr->internalRep.intValue);
+    else if (objPtr->internalRep.intValue == -1)
+        len = sprintf(buf, "end");
+    else {
+        len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
+    }
+    objPtr->bytes = Jim_Alloc(len + 1);
+    memcpy(objPtr->bytes, buf, len + 1);
+    objPtr->length = len;
+}
+
+int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    int idx, end = 0;
+    const char *str;
+    char *endptr;
+
+    
+    str = Jim_String(objPtr);
+
+    
+    if (strncmp(str, "end", 3) == 0) {
+        end = 1;
+        str += 3;
+        idx = 0;
+    }
+    else {
+        idx = jim_strtol(str, &endptr);
+
+        if (endptr == str) {
+            goto badindex;
+        }
+        str = endptr;
+    }
+
+    
+    if (*str == '+' || *str == '-') {
+        int sign = (*str == '+' ? 1 : -1);
+
+        idx += sign * jim_strtol(++str, &endptr);
+        if (str == endptr || *endptr) {
+            goto badindex;
+        }
+        str = endptr;
+    }
+    
+    while (isspace(UCHAR(*str))) {
+        str++;
+    }
+    if (*str) {
+        goto badindex;
+    }
+    if (end) {
+        if (idx > 0) {
+            idx = INT_MAX;
+        }
+        else {
+            
+            idx--;
+        }
+    }
+    else if (idx < 0) {
+        idx = -INT_MAX;
+    }
+
+    
+    Jim_FreeIntRep(interp, objPtr);
+    objPtr->typePtr = &indexObjType;
+    objPtr->internalRep.intValue = idx;
+    return JIM_OK;
+
+  badindex:
+    Jim_SetResultFormatted(interp,
+        "bad index \"%#s\": must be integer?[+-]integer? or end?[+-]integer?", objPtr);
+    return JIM_ERR;
+}
+
+int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
+{
+    
+    if (objPtr->typePtr == &intObjType) {
+        jim_wide val = JimWideValue(objPtr);
+
+        if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
+            *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
+            return JIM_OK;
+        }
+    }
+    if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
+        return JIM_ERR;
+    *indexPtr = objPtr->internalRep.intValue;
+    return JIM_OK;
+}
+
+
+
+static const char * const jimReturnCodes[] = {
+    "ok",
+    "error",
+    "return",
+    "break",
+    "continue",
+    "signal",
+    "exit",
+    "eval",
+    NULL
+};
+
+#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
+
+static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
+
+static const Jim_ObjType returnCodeObjType = {
+    "return-code",
+    NULL,
+    NULL,
+    NULL,
+    JIM_TYPE_NONE,
+};
+
+const char *Jim_ReturnCode(int code)
+{
+    if (code < 0 || code >= (int)jimReturnCodesSize) {
+        return "?";
+    }
+    else {
+        return jimReturnCodes[code];
+    }
+}
+
+int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    int returnCode;
+    jim_wide wideValue;
+
+    
+    if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR)
+        returnCode = (int)wideValue;
+    else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) {
+        Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr);
+        return JIM_ERR;
+    }
+    
+    Jim_FreeIntRep(interp, objPtr);
+    objPtr->typePtr = &returnCodeObjType;
+    objPtr->internalRep.intValue = returnCode;
+    return JIM_OK;
+}
+
+int Jim_GetReturnCode(Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr)
+{
+    if (objPtr->typePtr != &returnCodeObjType && SetReturnCodeFromAny(interp, objPtr) == JIM_ERR)
+        return JIM_ERR;
+    *intPtr = objPtr->internalRep.intValue;
+    return JIM_OK;
+}
+
+static int JimParseExprOperator(struct JimParserCtx *pc);
+static int JimParseExprNumber(struct JimParserCtx *pc);
+static int JimParseExprIrrational(struct JimParserCtx *pc);
+
+
+
+
+enum
+{
+    
+    
+    JIM_EXPROP_MUL = JIM_TT_EXPR_OP,             
+    JIM_EXPROP_DIV,
+    JIM_EXPROP_MOD,
+    JIM_EXPROP_SUB,
+    JIM_EXPROP_ADD,
+    JIM_EXPROP_LSHIFT,
+    JIM_EXPROP_RSHIFT,
+    JIM_EXPROP_ROTL,
+    JIM_EXPROP_ROTR,
+    JIM_EXPROP_LT,
+    JIM_EXPROP_GT,
+    JIM_EXPROP_LTE,
+    JIM_EXPROP_GTE,
+    JIM_EXPROP_NUMEQ,
+    JIM_EXPROP_NUMNE,
+    JIM_EXPROP_BITAND,          
+    JIM_EXPROP_BITXOR,
+    JIM_EXPROP_BITOR,
+
+    
+    JIM_EXPROP_LOGICAND,        
+    JIM_EXPROP_LOGICAND_LEFT,
+    JIM_EXPROP_LOGICAND_RIGHT,
+
+    
+    JIM_EXPROP_LOGICOR,         
+    JIM_EXPROP_LOGICOR_LEFT,
+    JIM_EXPROP_LOGICOR_RIGHT,
+
+    
+    
+    JIM_EXPROP_TERNARY,         
+    JIM_EXPROP_TERNARY_LEFT,
+    JIM_EXPROP_TERNARY_RIGHT,
+
+    
+    JIM_EXPROP_COLON,           
+    JIM_EXPROP_COLON_LEFT,
+    JIM_EXPROP_COLON_RIGHT,
+
+    JIM_EXPROP_POW,             
+
+
+    JIM_EXPROP_STREQ,           
+    JIM_EXPROP_STRNE,
+    JIM_EXPROP_STRIN,
+    JIM_EXPROP_STRNI,
+
+
+    JIM_EXPROP_NOT,             
+    JIM_EXPROP_BITNOT,
+    JIM_EXPROP_UNARYMINUS,
+    JIM_EXPROP_UNARYPLUS,
+
+    
+    JIM_EXPROP_FUNC_FIRST,      
+    JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
+    JIM_EXPROP_FUNC_ABS,
+    JIM_EXPROP_FUNC_DOUBLE,
+    JIM_EXPROP_FUNC_ROUND,
+    JIM_EXPROP_FUNC_RAND,
+    JIM_EXPROP_FUNC_SRAND,
+
+    
+    JIM_EXPROP_FUNC_SIN,        
+    JIM_EXPROP_FUNC_COS,
+    JIM_EXPROP_FUNC_TAN,
+    JIM_EXPROP_FUNC_ASIN,
+    JIM_EXPROP_FUNC_ACOS,
+    JIM_EXPROP_FUNC_ATAN,
+    JIM_EXPROP_FUNC_SINH,
+    JIM_EXPROP_FUNC_COSH,
+    JIM_EXPROP_FUNC_TANH,
+    JIM_EXPROP_FUNC_CEIL,
+    JIM_EXPROP_FUNC_FLOOR,
+    JIM_EXPROP_FUNC_EXP,
+    JIM_EXPROP_FUNC_LOG,
+    JIM_EXPROP_FUNC_LOG10,
+    JIM_EXPROP_FUNC_SQRT,
+    JIM_EXPROP_FUNC_POW,
+};
+
+struct JimExprState
+{
+    Jim_Obj **stack;
+    int stacklen;
+    int opcode;
+    int skip;
+};
+
+
+typedef struct Jim_ExprOperator
+{
+    const char *name;
+    int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
+    unsigned char precedence;
+    unsigned char arity;
+    unsigned char lazy;
+    unsigned char namelen;
+} Jim_ExprOperator;
+
+static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
+{
+    Jim_IncrRefCount(obj);
+    e->stack[e->stacklen++] = obj;
+}
+
+static Jim_Obj *ExprPop(struct JimExprState *e)
+{
+    return e->stack[--e->stacklen];
+}
+
+static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
+{
+    int intresult = 0;
+    int rc = JIM_OK;
+    Jim_Obj *A = ExprPop(e);
+    double dA, dC = 0;
+    jim_wide wA, wC = 0;
+
+    if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
+        intresult = 1;
+
+        switch (e->opcode) {
+            case JIM_EXPROP_FUNC_INT:
+                wC = wA;
+                break;
+            case JIM_EXPROP_FUNC_ROUND:
+                wC = wA;
+                break;
+            case JIM_EXPROP_FUNC_DOUBLE:
+                dC = wA;
+                intresult = 0;
+                break;
+            case JIM_EXPROP_FUNC_ABS:
+                wC = wA >= 0 ? wA : -wA;
+                break;
+            case JIM_EXPROP_UNARYMINUS:
+                wC = -wA;
+                break;
+            case JIM_EXPROP_UNARYPLUS:
+                wC = wA;
+                break;
+            case JIM_EXPROP_NOT:
+                wC = !wA;
+                break;
+            default:
+                abort();
+        }
+    }
+    else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) {
+        switch (e->opcode) {
+            case JIM_EXPROP_FUNC_INT:
+                wC = dA;
+                intresult = 1;
+                break;
+            case JIM_EXPROP_FUNC_ROUND:
+                wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
+                intresult = 1;
+                break;
+            case JIM_EXPROP_FUNC_DOUBLE:
+                dC = dA;
+                break;
+            case JIM_EXPROP_FUNC_ABS:
+                dC = dA >= 0 ? dA : -dA;
+                break;
+            case JIM_EXPROP_UNARYMINUS:
+                dC = -dA;
+                break;
+            case JIM_EXPROP_UNARYPLUS:
+                dC = dA;
+                break;
+            case JIM_EXPROP_NOT:
+                wC = !dA;
+                intresult = 1;
+                break;
+            default:
+                abort();
+        }
+    }
+
+    if (rc == JIM_OK) {
+        if (intresult) {
+            ExprPush(e, Jim_NewIntObj(interp, wC));
+        }
+        else {
+            ExprPush(e, Jim_NewDoubleObj(interp, dC));
+        }
+    }
+
+    Jim_DecrRefCount(interp, A);
+
+    return rc;
+}
+
+static double JimRandDouble(Jim_Interp *interp)
+{
+    unsigned long x;
+    JimRandomBytes(interp, &x, sizeof(x));
+
+    return (double)x / (unsigned long)~0;
+}
+
+static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *A = ExprPop(e);
+    jim_wide wA;
+
+    int rc = Jim_GetWide(interp, A, &wA);
+    if (rc == JIM_OK) {
+        switch (e->opcode) {
+            case JIM_EXPROP_BITNOT:
+                ExprPush(e, Jim_NewIntObj(interp, ~wA));
+                break;
+            case JIM_EXPROP_FUNC_SRAND:
+                JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA));
+                ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
+                break;
+            default:
+                abort();
+        }
+    }
+
+    Jim_DecrRefCount(interp, A);
+
+    return rc;
+}
+
+static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e)
+{
+    JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()"));
+
+    ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp)));
+
+    return JIM_OK;
+}
+
+#ifdef JIM_MATH_FUNCTIONS
+static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e)
+{
+    int rc;
+    Jim_Obj *A = ExprPop(e);
+    double dA, dC;
+
+    rc = Jim_GetDouble(interp, A, &dA);
+    if (rc == JIM_OK) {
+        switch (e->opcode) {
+            case JIM_EXPROP_FUNC_SIN:
+                dC = sin(dA);
+                break;
+            case JIM_EXPROP_FUNC_COS:
+                dC = cos(dA);
+                break;
+            case JIM_EXPROP_FUNC_TAN:
+                dC = tan(dA);
+                break;
+            case JIM_EXPROP_FUNC_ASIN:
+                dC = asin(dA);
+                break;
+            case JIM_EXPROP_FUNC_ACOS:
+                dC = acos(dA);
+                break;
+            case JIM_EXPROP_FUNC_ATAN:
+                dC = atan(dA);
+                break;
+            case JIM_EXPROP_FUNC_SINH:
+                dC = sinh(dA);
+                break;
+            case JIM_EXPROP_FUNC_COSH:
+                dC = cosh(dA);
+                break;
+            case JIM_EXPROP_FUNC_TANH:
+                dC = tanh(dA);
+                break;
+            case JIM_EXPROP_FUNC_CEIL:
+                dC = ceil(dA);
+                break;
+            case JIM_EXPROP_FUNC_FLOOR:
+                dC = floor(dA);
+                break;
+            case JIM_EXPROP_FUNC_EXP:
+                dC = exp(dA);
+                break;
+            case JIM_EXPROP_FUNC_LOG:
+                dC = log(dA);
+                break;
+            case JIM_EXPROP_FUNC_LOG10:
+                dC = log10(dA);
+                break;
+            case JIM_EXPROP_FUNC_SQRT:
+                dC = sqrt(dA);
+                break;
+            default:
+                abort();
+        }
+        ExprPush(e, Jim_NewDoubleObj(interp, dC));
+    }
+
+    Jim_DecrRefCount(interp, A);
+
+    return rc;
+}
+#endif
+
+
+static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *B = ExprPop(e);
+    Jim_Obj *A = ExprPop(e);
+    jim_wide wA, wB;
+    int rc = JIM_ERR;
+
+    if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) {
+        jim_wide wC;
+
+        rc = JIM_OK;
+
+        switch (e->opcode) {
+            case JIM_EXPROP_LSHIFT:
+                wC = wA << wB;
+                break;
+            case JIM_EXPROP_RSHIFT:
+                wC = wA >> wB;
+                break;
+            case JIM_EXPROP_BITAND:
+                wC = wA & wB;
+                break;
+            case JIM_EXPROP_BITXOR:
+                wC = wA ^ wB;
+                break;
+            case JIM_EXPROP_BITOR:
+                wC = wA | wB;
+                break;
+            case JIM_EXPROP_MOD:
+                if (wB == 0) {
+                    wC = 0;
+                    Jim_SetResultString(interp, "Division by zero", -1);
+                    rc = JIM_ERR;
+                }
+                else {
+                    int negative = 0;
+
+                    if (wB < 0) {
+                        wB = -wB;
+                        wA = -wA;
+                        negative = 1;
+                    }
+                    wC = wA % wB;
+                    if (wC < 0) {
+                        wC += wB;
+                    }
+                    if (negative) {
+                        wC = -wC;
+                    }
+                }
+                break;
+            case JIM_EXPROP_ROTL:
+            case JIM_EXPROP_ROTR:{
+                    
+                    unsigned long uA = (unsigned long)wA;
+                    unsigned long uB = (unsigned long)wB;
+                    const unsigned int S = sizeof(unsigned long) * 8;
+
+                    
+                    uB %= S;
+
+                    if (e->opcode == JIM_EXPROP_ROTR) {
+                        uB = S - uB;
+                    }
+                    wC = (unsigned long)(uA << uB) | (uA >> (S - uB));
+                    break;
+                }
+            default:
+                abort();
+        }
+        ExprPush(e, Jim_NewIntObj(interp, wC));
+
+    }
+
+    Jim_DecrRefCount(interp, A);
+    Jim_DecrRefCount(interp, B);
+
+    return rc;
+}
+
+
+
+static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
+{
+    int intresult = 0;
+    int rc = JIM_OK;
+    double dA, dB, dC = 0;
+    jim_wide wA, wB, wC = 0;
+
+    Jim_Obj *B = ExprPop(e);
+    Jim_Obj *A = ExprPop(e);
+
+    if ((A->typePtr != &doubleObjType || A->bytes) &&
+        (B->typePtr != &doubleObjType || B->bytes) &&
+        JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) {
+
+        
+
+        intresult = 1;
+
+        switch (e->opcode) {
+            case JIM_EXPROP_POW:
+            case JIM_EXPROP_FUNC_POW:
+                wC = JimPowWide(wA, wB);
+                break;
+            case JIM_EXPROP_ADD:
+                wC = wA + wB;
+                break;
+            case JIM_EXPROP_SUB:
+                wC = wA - wB;
+                break;
+            case JIM_EXPROP_MUL:
+                wC = wA * wB;
+                break;
+            case JIM_EXPROP_DIV:
+                if (wB == 0) {
+                    Jim_SetResultString(interp, "Division by zero", -1);
+                    rc = JIM_ERR;
+                }
+                else {
+                    if (wB < 0) {
+                        wB = -wB;
+                        wA = -wA;
+                    }
+                    wC = wA / wB;
+                    if (wA % wB < 0) {
+                        wC--;
+                    }
+                }
+                break;
+            case JIM_EXPROP_LT:
+                wC = wA < wB;
+                break;
+            case JIM_EXPROP_GT:
+                wC = wA > wB;
+                break;
+            case JIM_EXPROP_LTE:
+                wC = wA <= wB;
+                break;
+            case JIM_EXPROP_GTE:
+                wC = wA >= wB;
+                break;
+            case JIM_EXPROP_NUMEQ:
+                wC = wA == wB;
+                break;
+            case JIM_EXPROP_NUMNE:
+                wC = wA != wB;
+                break;
+            default:
+                abort();
+        }
+    }
+    else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
+        switch (e->opcode) {
+            case JIM_EXPROP_POW:
+            case JIM_EXPROP_FUNC_POW:
+#ifdef JIM_MATH_FUNCTIONS
+                dC = pow(dA, dB);
+#else
+                Jim_SetResultString(interp, "unsupported", -1);
+                rc = JIM_ERR;
+#endif
+                break;
+            case JIM_EXPROP_ADD:
+                dC = dA + dB;
+                break;
+            case JIM_EXPROP_SUB:
+                dC = dA - dB;
+                break;
+            case JIM_EXPROP_MUL:
+                dC = dA * dB;
+                break;
+            case JIM_EXPROP_DIV:
+                if (dB == 0) {
+#ifdef INFINITY
+                    dC = dA < 0 ? -INFINITY : INFINITY;
+#else
+                    dC = (dA < 0 ? -1.0 : 1.0) * strtod("Inf", NULL);
+#endif
+                }
+                else {
+                    dC = dA / dB;
+                }
+                break;
+            case JIM_EXPROP_LT:
+                wC = dA < dB;
+                intresult = 1;
+                break;
+            case JIM_EXPROP_GT:
+                wC = dA > dB;
+                intresult = 1;
+                break;
+            case JIM_EXPROP_LTE:
+                wC = dA <= dB;
+                intresult = 1;
+                break;
+            case JIM_EXPROP_GTE:
+                wC = dA >= dB;
+                intresult = 1;
+                break;
+            case JIM_EXPROP_NUMEQ:
+                wC = dA == dB;
+                intresult = 1;
+                break;
+            case JIM_EXPROP_NUMNE:
+                wC = dA != dB;
+                intresult = 1;
+                break;
+            default:
+                abort();
+        }
+    }
+    else {
+        
+
+        
+        int i = Jim_StringCompareObj(interp, A, B, 0);
+
+        intresult = 1;
+
+        switch (e->opcode) {
+            case JIM_EXPROP_LT:
+                wC = i < 0;
+                break;
+            case JIM_EXPROP_GT:
+                wC = i > 0;
+                break;
+            case JIM_EXPROP_LTE:
+                wC = i <= 0;
+                break;
+            case JIM_EXPROP_GTE:
+                wC = i >= 0;
+                break;
+            case JIM_EXPROP_NUMEQ:
+                wC = i == 0;
+                break;
+            case JIM_EXPROP_NUMNE:
+                wC = i != 0;
+                break;
+            default:
+                rc = JIM_ERR;
+                break;
+        }
+    }
+
+    if (rc == JIM_OK) {
+        if (intresult) {
+            ExprPush(e, Jim_NewIntObj(interp, wC));
+        }
+        else {
+            ExprPush(e, Jim_NewDoubleObj(interp, dC));
+        }
+    }
+
+    Jim_DecrRefCount(interp, A);
+    Jim_DecrRefCount(interp, B);
+
+    return rc;
+}
+
+static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj)
+{
+    int listlen;
+    int i;
+
+    listlen = Jim_ListLength(interp, listObjPtr);
+    for (i = 0; i < listlen; i++) {
+        Jim_Obj *objPtr;
+
+        Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
+
+        if (Jim_StringEqObj(objPtr, valObj)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *B = ExprPop(e);
+    Jim_Obj *A = ExprPop(e);
+
+    jim_wide wC;
+
+    switch (e->opcode) {
+        case JIM_EXPROP_STREQ:
+        case JIM_EXPROP_STRNE: {
+            int Alen, Blen;
+            const char *sA = Jim_GetString(A, &Alen);
+            const char *sB = Jim_GetString(B, &Blen);
+
+            if (e->opcode == JIM_EXPROP_STREQ) {
+                wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
+            }
+            else {
+                wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
+            }
+            break;
+        }
+        case JIM_EXPROP_STRIN:
+            wC = JimSearchList(interp, B, A);
+            break;
+        case JIM_EXPROP_STRNI:
+            wC = !JimSearchList(interp, B, A);
+            break;
+        default:
+            abort();
+    }
+    ExprPush(e, Jim_NewIntObj(interp, wC));
+
+    Jim_DecrRefCount(interp, A);
+    Jim_DecrRefCount(interp, B);
+
+    return JIM_OK;
+}
+
+static int ExprBool(Jim_Interp *interp, Jim_Obj *obj)
+{
+    long l;
+    double d;
+
+    if (Jim_GetLong(interp, obj, &l) == JIM_OK) {
+        return l != 0;
+    }
+    if (Jim_GetDouble(interp, obj, &d) == JIM_OK) {
+        return d != 0;
+    }
+    return -1;
+}
+
+static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *skip = ExprPop(e);
+    Jim_Obj *A = ExprPop(e);
+    int rc = JIM_OK;
+
+    switch (ExprBool(interp, A)) {
+        case 0:
+            
+            e->skip = JimWideValue(skip);
+            ExprPush(e, Jim_NewIntObj(interp, 0));
+            break;
+
+        case 1:
+            
+            break;
+
+        case -1:
+            
+            rc = JIM_ERR;
+    }
+    Jim_DecrRefCount(interp, A);
+    Jim_DecrRefCount(interp, skip);
+
+    return rc;
+}
+
+static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *skip = ExprPop(e);
+    Jim_Obj *A = ExprPop(e);
+    int rc = JIM_OK;
+
+    switch (ExprBool(interp, A)) {
+        case 0:
+            
+            break;
+
+        case 1:
+            
+            e->skip = JimWideValue(skip);
+            ExprPush(e, Jim_NewIntObj(interp, 1));
+            break;
+
+        case -1:
+            
+            rc = JIM_ERR;
+            break;
+    }
+    Jim_DecrRefCount(interp, A);
+    Jim_DecrRefCount(interp, skip);
+
+    return rc;
+}
+
+static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *A = ExprPop(e);
+    int rc = JIM_OK;
+
+    switch (ExprBool(interp, A)) {
+        case 0:
+            ExprPush(e, Jim_NewIntObj(interp, 0));
+            break;
+
+        case 1:
+            ExprPush(e, Jim_NewIntObj(interp, 1));
+            break;
+
+        case -1:
+            
+            rc = JIM_ERR;
+            break;
+    }
+    Jim_DecrRefCount(interp, A);
+
+    return rc;
+}
+
+static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *skip = ExprPop(e);
+    Jim_Obj *A = ExprPop(e);
+    int rc = JIM_OK;
+
+    
+    ExprPush(e, A);
+
+    switch (ExprBool(interp, A)) {
+        case 0:
+            
+            e->skip = JimWideValue(skip);
+            
+            ExprPush(e, Jim_NewIntObj(interp, 0));
+            break;
+
+        case 1:
+            
+            break;
+
+        case -1:
+            
+            rc = JIM_ERR;
+            break;
+    }
+    Jim_DecrRefCount(interp, A);
+    Jim_DecrRefCount(interp, skip);
+
+    return rc;
+}
+
+static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e)
+{
+    Jim_Obj *skip = ExprPop(e);
+    Jim_Obj *B = ExprPop(e);
+    Jim_Obj *A = ExprPop(e);
+
+    
+    if (ExprBool(interp, A)) {
+        
+        e->skip = JimWideValue(skip);
+        
+        ExprPush(e, B);
+    }
+
+    Jim_DecrRefCount(interp, skip);
+    Jim_DecrRefCount(interp, A);
+    Jim_DecrRefCount(interp, B);
+    return JIM_OK;
+}
+
+static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e)
+{
+    return JIM_OK;
+}
+
+enum
+{
+    LAZY_NONE,
+    LAZY_OP,
+    LAZY_LEFT,
+    LAZY_RIGHT
+};
+
+#define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
+
+static const struct Jim_ExprOperator Jim_ExprOperators[] = {
+    OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
+    OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
+    OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),
+
+    OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
+    OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),
+
+    OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
+    OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),
+
+    OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
+    OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),
+
+    OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
+    OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
+    OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
+    OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),
+
+    OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
+    OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),
+
+    OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
+    OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
+    OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),
+
+    OPRINIT("&&", 10, 2, NULL, LAZY_OP),
+    OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
+    OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
+
+    OPRINIT("||", 9, 2, NULL, LAZY_OP),
+    OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
+    OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
+
+    OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
+    OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
+    OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
+
+    OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
+    OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
+    OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
+
+    OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),
+
+    OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
+    OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),
+
+    OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
+    OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),
+
+    OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
+    OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
+    OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
+    OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
+
+
+
+    OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
+    OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
+    OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
+    OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
+    OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
+    OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE),
+
+#ifdef JIM_MATH_FUNCTIONS
+    OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
+    OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE),
+#endif
+};
+#undef OPRINIT
+
+#define JIM_EXPR_OPERATORS_NUM \
+    (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
+
+static int JimParseExpression(struct JimParserCtx *pc)
+{
+    
+    while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) {
+        if (*pc->p == '\n') {
+            pc->linenr++;
+        }
+        pc->p++;
+        pc->len--;
+    }
+
+    if (pc->len == 0) {
+        pc->tstart = pc->tend = pc->p;
+        pc->tline = pc->linenr;
+        pc->tt = JIM_TT_EOL;
+        pc->eof = 1;
+        return JIM_OK;
+    }
+    switch (*(pc->p)) {
+        case '(':
+                pc->tt = JIM_TT_SUBEXPR_START;
+                goto singlechar;
+        case ')':
+                pc->tt = JIM_TT_SUBEXPR_END;
+                goto singlechar;
+        case ',':
+            pc->tt = JIM_TT_SUBEXPR_COMMA;
+singlechar:
+            pc->tstart = pc->tend = pc->p;
+            pc->tline = pc->linenr;
+            pc->p++;
+            pc->len--;
+            break;
+        case '[':
+            return JimParseCmd(pc);
+        case '$':
+            if (JimParseVar(pc) == JIM_ERR)
+                return JimParseExprOperator(pc);
+            else {
+                
+                if (pc->tt == JIM_TT_EXPRSUGAR) {
+                    return JIM_ERR;
+                }
+                return JIM_OK;
+            }
+            break;
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+        case '.':
+            return JimParseExprNumber(pc);
+        case '"':
+            return JimParseQuote(pc);
+        case '{':
+            return JimParseBrace(pc);
+
+        case 'N':
+        case 'I':
+        case 'n':
+        case 'i':
+            if (JimParseExprIrrational(pc) == JIM_ERR)
+                return JimParseExprOperator(pc);
+            break;
+        default:
+            return JimParseExprOperator(pc);
+            break;
+    }
+    return JIM_OK;
+}
+
+static int JimParseExprNumber(struct JimParserCtx *pc)
+{
+    int allowdot = 1;
+    int base = 10;
+
+    
+    pc->tt = JIM_TT_EXPR_INT;
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+
+    
+    if (pc->p[0] == '0') {
+        switch (pc->p[1]) {
+            case 'x':
+            case 'X':
+                base = 16;
+                allowdot = 0;
+                pc->p += 2;
+                pc->len -= 2;
+                break;
+            case 'o':
+            case 'O':
+                base = 8;
+                allowdot = 0;
+                pc->p += 2;
+                pc->len -= 2;
+                break;
+            case 'b':
+            case 'B':
+                base = 2;
+                allowdot = 0;
+                pc->p += 2;
+                pc->len -= 2;
+                break;
+        }
+    }
+
+    while (isdigit(UCHAR(*pc->p))
+        || (base == 16 && isxdigit(UCHAR(*pc->p)))
+        || (base == 8 && *pc->p >= '0' && *pc->p <= '7')
+        || (base == 2 && (*pc->p == '0' || *pc->p == '1'))
+        || (allowdot && *pc->p == '.')
+        ) {
+        if (*pc->p == '.') {
+            allowdot = 0;
+            pc->tt = JIM_TT_EXPR_DOUBLE;
+        }
+        pc->p++;
+        pc->len--;
+        if (base == 10 && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
+                || isdigit(UCHAR(pc->p[1])))) {
+            pc->p += 2;
+            pc->len -= 2;
+            pc->tt = JIM_TT_EXPR_DOUBLE;
+        }
+    }
+    pc->tend = pc->p - 1;
+    return JIM_OK;
+}
+
+static int JimParseExprIrrational(struct JimParserCtx *pc)
+{
+    const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
+    const char **token;
+
+    for (token = Tokens; *token != NULL; token++) {
+        int len = strlen(*token);
+
+        if (strncmp(*token, pc->p, len) == 0) {
+            pc->tstart = pc->p;
+            pc->tend = pc->p + len - 1;
+            pc->p += len;
+            pc->len -= len;
+            pc->tline = pc->linenr;
+            pc->tt = JIM_TT_EXPR_DOUBLE;
+            return JIM_OK;
+        }
+    }
+    return JIM_ERR;
+}
+
+static int JimParseExprOperator(struct JimParserCtx *pc)
+{
+    int i;
+    int bestIdx = -1, bestLen = 0;
+
+    
+    for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
+        const char * const opname = Jim_ExprOperators[i].name;
+        const int oplen = Jim_ExprOperators[i].namelen;
+
+        if (opname == NULL || opname[0] != pc->p[0]) {
+            continue;
+        }
+
+        if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
+            bestIdx = i + JIM_TT_EXPR_OP;
+            bestLen = oplen;
+        }
+    }
+    if (bestIdx == -1) {
+        return JIM_ERR;
+    }
+
+    
+    if (bestIdx >= JIM_EXPROP_FUNC_FIRST) {
+        const char *p = pc->p + bestLen;
+        int len = pc->len - bestLen;
+
+        while (len && isspace(UCHAR(*p))) {
+            len--;
+            p++;
+        }
+        if (*p != '(') {
+            return JIM_ERR;
+        }
+    }
+    pc->tstart = pc->p;
+    pc->tend = pc->p + bestLen - 1;
+    pc->p += bestLen;
+    pc->len -= bestLen;
+    pc->tline = pc->linenr;
+
+    pc->tt = bestIdx;
+    return JIM_OK;
+}
+
+static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
+{
+    static Jim_ExprOperator dummy_op;
+    if (opcode < JIM_TT_EXPR_OP) {
+        return &dummy_op;
+    }
+    return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
+}
+
+const char *jim_tt_name(int type)
+{
+    static const char * const tt_names[JIM_TT_EXPR_OP] =
+        { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT",
+            "DBL", "$()" };
+    if (type < JIM_TT_EXPR_OP) {
+        return tt_names[type];
+    }
+    else {
+        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
+        static char buf[20];
+
+        if (op->name) {
+            return op->name;
+        }
+        sprintf(buf, "(%d)", type);
+        return buf;
+    }
+}
+
+static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+
+static const Jim_ObjType exprObjType = {
+    "expression",
+    FreeExprInternalRep,
+    DupExprInternalRep,
+    NULL,
+    JIM_TYPE_REFERENCES,
+};
+
+
+typedef struct ExprByteCode
+{
+    ScriptToken *token;         
+    int len;                    
+    int inUse;                  
+} ExprByteCode;
+
+static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
+{
+    int i;
+
+    for (i = 0; i < expr->len; i++) {
+        Jim_DecrRefCount(interp, expr->token[i].objPtr);
+    }
+    Jim_Free(expr->token);
+    Jim_Free(expr);
+}
+
+static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    ExprByteCode *expr = (void *)objPtr->internalRep.ptr;
+
+    if (expr) {
+        if (--expr->inUse != 0) {
+            return;
+        }
+
+        ExprFreeByteCode(interp, expr);
+    }
+}
+
+static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    JIM_NOTUSED(interp);
+    JIM_NOTUSED(srcPtr);
+
+    
+    dupPtr->typePtr = NULL;
+}
+
+
+static int ExprCheckCorrectness(ExprByteCode * expr)
+{
+    int i;
+    int stacklen = 0;
+    int ternary = 0;
+
+    for (i = 0; i < expr->len; i++) {
+        ScriptToken *t = &expr->token[i];
+        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
+
+        stacklen -= op->arity;
+        if (stacklen < 0) {
+            break;
+        }
+        if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
+            ternary++;
+        }
+        else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
+            ternary--;
+        }
+
+        
+        stacklen++;
+    }
+    if (stacklen != 1 || ternary != 0) {
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
+{
+    int i;
+
+    int leftindex, arity, offset;
+
+    
+    leftindex = expr->len - 1;
+
+    arity = 1;
+    while (arity) {
+        ScriptToken *tt = &expr->token[leftindex];
+
+        if (tt->type >= JIM_TT_EXPR_OP) {
+            arity += JimExprOperatorInfoByOpcode(tt->type)->arity;
+        }
+        arity--;
+        if (--leftindex < 0) {
+            return JIM_ERR;
+        }
+    }
+    leftindex++;
+
+    
+    memmove(&expr->token[leftindex + 2], &expr->token[leftindex],
+        sizeof(*expr->token) * (expr->len - leftindex));
+    expr->len += 2;
+    offset = (expr->len - leftindex) - 1;
+
+    expr->token[leftindex + 1].type = t->type + 1;
+    expr->token[leftindex + 1].objPtr = interp->emptyObj;
+
+    expr->token[leftindex].type = JIM_TT_EXPR_INT;
+    expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset);
+
+    
+    expr->token[expr->len].objPtr = interp->emptyObj;
+    expr->token[expr->len].type = t->type + 2;
+    expr->len++;
+
+    
+    for (i = leftindex - 1; i > 0; i--) {
+        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
+        if (op->lazy == LAZY_LEFT) {
+            if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
+                JimWideValue(expr->token[i - 1].objPtr) += 2;
+            }
+        }
+    }
+    return JIM_OK;
+}
+
+static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t)
+{
+    struct ScriptToken *token = &expr->token[expr->len];
+    const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
+
+    if (op->lazy == LAZY_OP) {
+        if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) {
+            Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name);
+            return JIM_ERR;
+        }
+    }
+    else {
+        token->objPtr = interp->emptyObj;
+        token->type = t->type;
+        expr->len++;
+    }
+    return JIM_OK;
+}
+
+static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index)
+{
+    int ternary_count = 1;
+
+    right_index--;
+
+    while (right_index > 1) {
+        if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) {
+            ternary_count--;
+        }
+        else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) {
+            ternary_count++;
+        }
+        else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) {
+            return right_index;
+        }
+        right_index--;
+    }
+
+    
+    return -1;
+}
+
+static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index)
+{
+    int i = right_index - 1;
+    int ternary_count = 1;
+
+    while (i > 1) {
+        if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) {
+            if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) {
+                *prev_right_index = i - 2;
+                *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index);
+                return 1;
+            }
+        }
+        else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) {
+            if (ternary_count == 0) {
+                return 0;
+            }
+            ternary_count++;
+        }
+        i--;
+    }
+    return 0;
+}
+
+static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr)
+{
+    int i;
+
+    for (i = expr->len - 1; i > 1; i--) {
+        int prev_right_index;
+        int prev_left_index;
+        int j;
+        ScriptToken tmp;
+
+        if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) {
+            continue;
+        }
+
+        
+        if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) {
+            continue;
+        }
+
+        tmp = expr->token[prev_right_index];
+        for (j = prev_right_index; j < i; j++) {
+            expr->token[j] = expr->token[j + 1];
+        }
+        expr->token[i] = tmp;
+
+        JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index);
+
+        
+        i++;
+    }
+}
+
+static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj)
+{
+    Jim_Stack stack;
+    ExprByteCode *expr;
+    int ok = 1;
+    int i;
+    int prevtt = JIM_TT_NONE;
+    int have_ternary = 0;
+
+    
+    int count = tokenlist->count - 1;
+
+    expr = Jim_Alloc(sizeof(*expr));
+    expr->inUse = 1;
+    expr->len = 0;
+
+    Jim_InitStack(&stack);
+
+    for (i = 0; i < tokenlist->count; i++) {
+        ParseToken *t = &tokenlist->list[i];
+        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
+
+        if (op->lazy == LAZY_OP) {
+            count += 2;
+            
+            if (t->type == JIM_EXPROP_TERNARY) {
+                have_ternary = 1;
+            }
+        }
+    }
+
+    expr->token = Jim_Alloc(sizeof(ScriptToken) * count);
+
+    for (i = 0; i < tokenlist->count && ok; i++) {
+        ParseToken *t = &tokenlist->list[i];
+
+        
+        struct ScriptToken *token = &expr->token[expr->len];
+
+        if (t->type == JIM_TT_EOL) {
+            break;
+        }
+
+        switch (t->type) {
+            case JIM_TT_STR:
+            case JIM_TT_ESC:
+            case JIM_TT_VAR:
+            case JIM_TT_DICTSUGAR:
+            case JIM_TT_EXPRSUGAR:
+            case JIM_TT_CMD:
+                token->type = t->type;
+strexpr:
+                token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
+                if (t->type == JIM_TT_CMD) {
+                    
+                    JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
+                }
+                expr->len++;
+                break;
+
+            case JIM_TT_EXPR_INT:
+            case JIM_TT_EXPR_DOUBLE:
+                {
+                    char *endptr;
+                    if (t->type == JIM_TT_EXPR_INT) {
+                        token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
+                    }
+                    else {
+                        token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
+                    }
+                    if (endptr != t->token + t->len) {
+                        
+                        Jim_FreeNewObj(interp, token->objPtr);
+                        token->type = JIM_TT_STR;
+                        goto strexpr;
+                    }
+                    token->type = t->type;
+                    expr->len++;
+                }
+                break;
+
+            case JIM_TT_SUBEXPR_START:
+                Jim_StackPush(&stack, t);
+                prevtt = JIM_TT_NONE;
+                continue;
+
+            case JIM_TT_SUBEXPR_COMMA:
+                
+                continue;
+
+            case JIM_TT_SUBEXPR_END:
+                ok = 0;
+                while (Jim_StackLen(&stack)) {
+                    ParseToken *tt = Jim_StackPop(&stack);
+
+                    if (tt->type == JIM_TT_SUBEXPR_START) {
+                        ok = 1;
+                        break;
+                    }
+
+                    if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
+                        goto err;
+                    }
+                }
+                if (!ok) {
+                    Jim_SetResultString(interp, "Unexpected close parenthesis", -1);
+                    goto err;
+                }
+                break;
+
+
+            default:{
+                    
+                    const struct Jim_ExprOperator *op;
+                    ParseToken *tt;
+
+                    
+                    if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) {
+                        if (t->type == JIM_EXPROP_SUB) {
+                            t->type = JIM_EXPROP_UNARYMINUS;
+                        }
+                        else if (t->type == JIM_EXPROP_ADD) {
+                            t->type = JIM_EXPROP_UNARYPLUS;
+                        }
+                    }
+
+                    op = JimExprOperatorInfoByOpcode(t->type);
+
+                    
+                    while ((tt = Jim_StackPeek(&stack)) != NULL) {
+                        const struct Jim_ExprOperator *tt_op =
+                            JimExprOperatorInfoByOpcode(tt->type);
+
+                        
+
+                        if (op->arity != 1 && tt_op->precedence >= op->precedence) {
+                            if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
+                                ok = 0;
+                                goto err;
+                            }
+                            Jim_StackPop(&stack);
+                        }
+                        else {
+                            break;
+                        }
+                    }
+                    Jim_StackPush(&stack, t);
+                    break;
+                }
+        }
+        prevtt = t->type;
+    }
+
+    
+    while (Jim_StackLen(&stack)) {
+        ParseToken *tt = Jim_StackPop(&stack);
+
+        if (tt->type == JIM_TT_SUBEXPR_START) {
+            ok = 0;
+            Jim_SetResultString(interp, "Missing close parenthesis", -1);
+            goto err;
+        }
+        if (ExprAddOperator(interp, expr, tt) != JIM_OK) {
+            ok = 0;
+            goto err;
+        }
+    }
+
+    if (have_ternary) {
+        ExprTernaryReorderExpression(interp, expr);
+    }
+
+  err:
+    
+    Jim_FreeStack(&stack);
+
+    for (i = 0; i < expr->len; i++) {
+        Jim_IncrRefCount(expr->token[i].objPtr);
+    }
+
+    if (!ok) {
+        ExprFreeByteCode(interp, expr);
+        return NULL;
+    }
+
+    return expr;
+}
+
+
+static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
+{
+    int exprTextLen;
+    const char *exprText;
+    struct JimParserCtx parser;
+    struct ExprByteCode *expr;
+    ParseTokenList tokenlist;
+    int line;
+    Jim_Obj *fileNameObj;
+    int rc = JIM_ERR;
+
+    
+    if (objPtr->typePtr == &sourceObjType) {
+        fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
+        line = objPtr->internalRep.sourceValue.lineNumber;
+    }
+    else {
+        fileNameObj = interp->emptyObj;
+        line = 1;
+    }
+    Jim_IncrRefCount(fileNameObj);
+
+    exprText = Jim_GetString(objPtr, &exprTextLen);
+
+    
+    ScriptTokenListInit(&tokenlist);
+
+    JimParserInit(&parser, exprText, exprTextLen, line);
+    while (!parser.eof) {
+        if (JimParseExpression(&parser) != JIM_OK) {
+            ScriptTokenListFree(&tokenlist);
+          invalidexpr:
+            Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr);
+            expr = NULL;
+            goto err;
+        }
+
+        ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
+            parser.tline);
+    }
+
+#ifdef DEBUG_SHOW_EXPR_TOKENS
+    {
+        int i;
+        printf("==== Expr Tokens ====\n");
+        for (i = 0; i < tokenlist.count; i++) {
+            printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
+                tokenlist.list[i].len, tokenlist.list[i].token);
+        }
+    }
+#endif
+
+    
+    expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
+
+    
+    ScriptTokenListFree(&tokenlist);
+
+    if (!expr) {
+        goto err;
+    }
+
+#ifdef DEBUG_SHOW_EXPR
+    {
+        int i;
+
+        printf("==== Expr ====\n");
+        for (i = 0; i < expr->len; i++) {
+            ScriptToken *t = &expr->token[i];
+
+            printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr));
+        }
+    }
+#endif
+
+    
+    if (ExprCheckCorrectness(expr) != JIM_OK) {
+        ExprFreeByteCode(interp, expr);
+        goto invalidexpr;
+    }
+
+    rc = JIM_OK;
+
+  err:
+    
+    Jim_DecrRefCount(interp, fileNameObj);
+    Jim_FreeIntRep(interp, objPtr);
+    Jim_SetIntRepPtr(objPtr, expr);
+    objPtr->typePtr = &exprObjType;
+    return rc;
+}
+
+static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    if (objPtr->typePtr != &exprObjType) {
+        if (SetExprFromAny(interp, objPtr) != JIM_OK) {
+            return NULL;
+        }
+    }
+    return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
+}
+
+#define JIM_EE_STATICSTACK_LEN 10
+
+int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr)
+{
+    ExprByteCode *expr;
+    Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN];
+    int i;
+    int retcode = JIM_OK;
+    struct JimExprState e;
+
+    expr = JimGetExpression(interp, exprObjPtr);
+    if (!expr) {
+        return JIM_ERR;         
+    }
+
+#ifdef JIM_OPTIMIZATION
+    {
+        Jim_Obj *objPtr;
+
+
+        switch (expr->len) {
+            case 1:
+                if (expr->token[0].type == JIM_TT_EXPR_INT) {
+                    *exprResultPtrPtr = expr->token[0].objPtr;
+                    Jim_IncrRefCount(*exprResultPtrPtr);
+                    return JIM_OK;
+                }
+                if (expr->token[0].type == JIM_TT_VAR) {
+                    objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
+                    if (objPtr) {
+                        *exprResultPtrPtr = objPtr;
+                        Jim_IncrRefCount(*exprResultPtrPtr);
+                        return JIM_OK;
+                    }
+                }
+                break;
+
+            case 2:
+                if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
+                    jim_wide wideValue;
+
+                    objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
+                    if (objPtr && JimIsWide(objPtr)
+                        && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
+                        *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
+                        Jim_IncrRefCount(*exprResultPtrPtr);
+                        return JIM_OK;
+                    }
+                }
+                break;
+
+            case 3:
+                if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
+                        || expr->token[1].type == JIM_TT_VAR)) {
+                    switch (expr->token[2].type) {
+                        case JIM_EXPROP_LT:
+                        case JIM_EXPROP_LTE:
+                        case JIM_EXPROP_GT:
+                        case JIM_EXPROP_GTE:
+                        case JIM_EXPROP_NUMEQ:
+                        case JIM_EXPROP_NUMNE:{
+                                
+                                jim_wide wideValueA;
+                                jim_wide wideValueB;
+
+                                objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
+                                if (objPtr && JimIsWide(objPtr)
+                                    && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
+                                    if (expr->token[1].type == JIM_TT_VAR) {
+                                        objPtr =
+                                            Jim_GetVariable(interp, expr->token[1].objPtr,
+                                            JIM_NONE);
+                                    }
+                                    else {
+                                        objPtr = expr->token[1].objPtr;
+                                    }
+                                    if (objPtr && JimIsWide(objPtr)
+                                        && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
+                                        int cmpRes;
+
+                                        switch (expr->token[2].type) {
+                                            case JIM_EXPROP_LT:
+                                                cmpRes = wideValueA < wideValueB;
+                                                break;
+                                            case JIM_EXPROP_LTE:
+                                                cmpRes = wideValueA <= wideValueB;
+                                                break;
+                                            case JIM_EXPROP_GT:
+                                                cmpRes = wideValueA > wideValueB;
+                                                break;
+                                            case JIM_EXPROP_GTE:
+                                                cmpRes = wideValueA >= wideValueB;
+                                                break;
+                                            case JIM_EXPROP_NUMEQ:
+                                                cmpRes = wideValueA == wideValueB;
+                                                break;
+                                            case JIM_EXPROP_NUMNE:
+                                                cmpRes = wideValueA != wideValueB;
+                                                break;
+                                            default:   
+                                                cmpRes = 0;
+                                        }
+                                        *exprResultPtrPtr =
+                                            cmpRes ? interp->trueObj : interp->falseObj;
+                                        Jim_IncrRefCount(*exprResultPtrPtr);
+                                        return JIM_OK;
+                                    }
+                                }
+                            }
+                    }
+                }
+                break;
+        }
+    }
+#endif
+
+    expr->inUse++;
+
+    
+
+    if (expr->len > JIM_EE_STATICSTACK_LEN)
+        e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len);
+    else
+        e.stack = staticStack;
+
+    e.stacklen = 0;
+
+    
+    for (i = 0; i < expr->len && retcode == JIM_OK; i++) {
+        Jim_Obj *objPtr;
+
+        switch (expr->token[i].type) {
+            case JIM_TT_EXPR_INT:
+            case JIM_TT_EXPR_DOUBLE:
+            case JIM_TT_STR:
+                ExprPush(&e, expr->token[i].objPtr);
+                break;
+
+            case JIM_TT_VAR:
+                objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG);
+                if (objPtr) {
+                    ExprPush(&e, objPtr);
+                }
+                else {
+                    retcode = JIM_ERR;
+                }
+                break;
+
+            case JIM_TT_DICTSUGAR:
+                objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr);
+                if (objPtr) {
+                    ExprPush(&e, objPtr);
+                }
+                else {
+                    retcode = JIM_ERR;
+                }
+                break;
+
+            case JIM_TT_ESC:
+                retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE);
+                if (retcode == JIM_OK) {
+                    ExprPush(&e, objPtr);
+                }
+                break;
+
+            case JIM_TT_CMD:
+                retcode = Jim_EvalObj(interp, expr->token[i].objPtr);
+                if (retcode == JIM_OK) {
+                    ExprPush(&e, Jim_GetResult(interp));
+                }
+                break;
+
+            default:{
+                    
+                    e.skip = 0;
+                    e.opcode = expr->token[i].type;
+
+                    retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e);
+                    
+                    i += e.skip;
+                    continue;
+                }
+        }
+    }
+
+    expr->inUse--;
+
+    if (retcode == JIM_OK) {
+        *exprResultPtrPtr = ExprPop(&e);
+    }
+    else {
+        for (i = 0; i < e.stacklen; i++) {
+            Jim_DecrRefCount(interp, e.stack[i]);
+        }
+    }
+    if (e.stack != staticStack) {
+        Jim_Free(e.stack);
+    }
+    return retcode;
+}
+
+int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
+{
+    int retcode;
+    jim_wide wideValue;
+    double doubleValue;
+    Jim_Obj *exprResultPtr;
+
+    retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr);
+    if (retcode != JIM_OK)
+        return retcode;
+
+    if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) {
+        if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) {
+            Jim_DecrRefCount(interp, exprResultPtr);
+            return JIM_ERR;
+        }
+        else {
+            Jim_DecrRefCount(interp, exprResultPtr);
+            *boolPtr = doubleValue != 0;
+            return JIM_OK;
+        }
+    }
+    *boolPtr = wideValue != 0;
+
+    Jim_DecrRefCount(interp, exprResultPtr);
+    return JIM_OK;
+}
+
+
+
+
+typedef struct ScanFmtPartDescr
+{
+    char *arg;                  
+    char *prefix;               
+    size_t width;               
+    int pos;                    
+    char type;                  
+    char modifier;              
+} ScanFmtPartDescr;
+
+
+typedef struct ScanFmtStringObj
+{
+    jim_wide size;              
+    char *stringRep;            
+    size_t count;               
+    size_t convCount;           
+    size_t maxPos;              
+    const char *error;          
+    char *scratch;              
+    ScanFmtPartDescr descr[1];  
+} ScanFmtStringObj;
+
+
+static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
+static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
+static void UpdateStringOfScanFmt(Jim_Obj *objPtr);
+
+static const Jim_ObjType scanFmtStringObjType = {
+    "scanformatstring",
+    FreeScanFmtInternalRep,
+    DupScanFmtInternalRep,
+    UpdateStringOfScanFmt,
+    JIM_TYPE_NONE,
+};
+
+void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    JIM_NOTUSED(interp);
+    Jim_Free((char *)objPtr->internalRep.ptr);
+    objPtr->internalRep.ptr = 0;
+}
+
+void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    size_t size = (size_t) ((ScanFmtStringObj *) srcPtr->internalRep.ptr)->size;
+    ScanFmtStringObj *newVec = (ScanFmtStringObj *) Jim_Alloc(size);
+
+    JIM_NOTUSED(interp);
+    memcpy(newVec, srcPtr->internalRep.ptr, size);
+    dupPtr->internalRep.ptr = newVec;
+    dupPtr->typePtr = &scanFmtStringObjType;
+}
+
+void UpdateStringOfScanFmt(Jim_Obj *objPtr)
+{
+    char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
+
+    objPtr->bytes = Jim_StrDup(bytes);
+    objPtr->length = strlen(bytes);
+}
+
+
+static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    ScanFmtStringObj *fmtObj;
+    char *buffer;
+    int maxCount, i, approxSize, lastPos = -1;
+    const char *fmt = objPtr->bytes;
+    int maxFmtLen = objPtr->length;
+    const char *fmtEnd = fmt + maxFmtLen;
+    int curr;
+
+    Jim_FreeIntRep(interp, objPtr);
+    
+    for (i = 0, maxCount = 0; i < maxFmtLen; ++i)
+        if (fmt[i] == '%')
+            ++maxCount;
+    
+    approxSize = sizeof(ScanFmtStringObj)       
+        +(maxCount + 1) * sizeof(ScanFmtPartDescr)      
+        +maxFmtLen * sizeof(char) + 3 + 1       
+        + maxFmtLen * sizeof(char) + 1  
+        + maxFmtLen * sizeof(char)      
+        +(maxCount + 1) * sizeof(char)  
+        +1;                     
+    fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize);
+    memset(fmtObj, 0, approxSize);
+    fmtObj->size = approxSize;
+    fmtObj->maxPos = 0;
+    fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1];
+    fmtObj->stringRep = fmtObj->scratch + maxFmtLen + 3 + 1;
+    memcpy(fmtObj->stringRep, fmt, maxFmtLen);
+    buffer = fmtObj->stringRep + maxFmtLen + 1;
+    objPtr->internalRep.ptr = fmtObj;
+    objPtr->typePtr = &scanFmtStringObjType;
+    for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) {
+        int width = 0, skip;
+        ScanFmtPartDescr *descr = &fmtObj->descr[curr];
+
+        fmtObj->count++;
+        descr->width = 0;       
+        
+        if (*fmt != '%' || fmt[1] == '%') {
+            descr->type = 0;
+            descr->prefix = &buffer[i];
+            for (; fmt < fmtEnd; ++fmt) {
+                if (*fmt == '%') {
+                    if (fmt[1] != '%')
+                        break;
+                    ++fmt;
+                }
+                buffer[i++] = *fmt;
+            }
+            buffer[i++] = 0;
+        }
+        
+        ++fmt;
+        
+        if (fmt >= fmtEnd)
+            goto done;
+        descr->pos = 0;         
+        if (*fmt == '*') {
+            descr->pos = -1;    
+            ++fmt;
+        }
+        else
+            fmtObj->convCount++;        
+        
+        if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
+            fmt += skip;
+            
+            if (descr->pos != -1 && *fmt == '$') {
+                int prev;
+
+                ++fmt;
+                descr->pos = width;
+                width = 0;
+                
+                if ((lastPos == 0 && descr->pos > 0)
+                    || (lastPos > 0 && descr->pos == 0)) {
+                    fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers";
+                    return JIM_ERR;
+                }
+                
+                for (prev = 0; prev < curr; ++prev) {
+                    if (fmtObj->descr[prev].pos == -1)
+                        continue;
+                    if (fmtObj->descr[prev].pos == descr->pos) {
+                        fmtObj->error =
+                            "variable is assigned by multiple \"%n$\" conversion specifiers";
+                        return JIM_ERR;
+                    }
+                }
+                
+                if (sscanf(fmt, "%d%n", &width, &skip) == 1) {
+                    descr->width = width;
+                    fmt += skip;
+                }
+                if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos)
+                    fmtObj->maxPos = descr->pos;
+            }
+            else {
+                
+                descr->width = width;
+            }
+        }
+        
+        if (lastPos == -1)
+            lastPos = descr->pos;
+        
+        if (*fmt == '[') {
+            int swapped = 1, beg = i, end, j;
+
+            descr->type = '[';
+            descr->arg = &buffer[i];
+            ++fmt;
+            if (*fmt == '^')
+                buffer[i++] = *fmt++;
+            if (*fmt == ']')
+                buffer[i++] = *fmt++;
+            while (*fmt && *fmt != ']')
+                buffer[i++] = *fmt++;
+            if (*fmt != ']') {
+                fmtObj->error = "unmatched [ in format string";
+                return JIM_ERR;
+            }
+            end = i;
+            buffer[i++] = 0;
+            
+            while (swapped) {
+                swapped = 0;
+                for (j = beg + 1; j < end - 1; ++j) {
+                    if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) {
+                        char tmp = buffer[j - 1];
+
+                        buffer[j - 1] = buffer[j + 1];
+                        buffer[j + 1] = tmp;
+                        swapped = 1;
+                    }
+                }
+            }
+        }
+        else {
+            
+            if (strchr("hlL", *fmt) != 0)
+                descr->modifier = tolower((int)*fmt++);
+
+            descr->type = *fmt;
+            if (strchr("efgcsndoxui", *fmt) == 0) {
+                fmtObj->error = "bad scan conversion character";
+                return JIM_ERR;
+            }
+            else if (*fmt == 'c' && descr->width != 0) {
+                fmtObj->error = "field width may not be specified in %c " "conversion";
+                return JIM_ERR;
+            }
+            else if (*fmt == 'u' && descr->modifier == 'l') {
+                fmtObj->error = "unsigned wide not supported";
+                return JIM_ERR;
+            }
+        }
+        curr++;
+    }
+  done:
+    return JIM_OK;
+}
+
+
+
+#define FormatGetCnvCount(_fo_) \
+    ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->convCount
+#define FormatGetMaxPos(_fo_) \
+    ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->maxPos
+#define FormatGetError(_fo_) \
+    ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->error
+
+static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str)
+{
+    char *buffer = Jim_StrDup(str);
+    char *p = buffer;
+
+    while (*str) {
+        int c;
+        int n;
+
+        if (!sdescr && isspace(UCHAR(*str)))
+            break;              
+
+        n = utf8_tounicode(str, &c);
+        if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN))
+            break;
+        while (n--)
+            *p++ = *str++;
+    }
+    *p = 0;
+    return Jim_NewStringObjNoAlloc(interp, buffer, p - buffer);
+}
+
+
+static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen,
+    ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr)
+{
+    const char *tok;
+    const ScanFmtPartDescr *descr = &fmtObj->descr[idx];
+    size_t scanned = 0;
+    size_t anchor = pos;
+    int i;
+    Jim_Obj *tmpObj = NULL;
+
+    
+    *valObjPtr = 0;
+    if (descr->prefix) {
+        
+        for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
+            
+            if (isspace(UCHAR(descr->prefix[i])))
+                while (pos < strLen && isspace(UCHAR(str[pos])))
+                    ++pos;
+            else if (descr->prefix[i] != str[pos])
+                break;          
+            else
+                ++pos;          
+        }
+        if (pos >= strLen) {
+            return -1;          
+        }
+        else if (descr->prefix[i] != 0)
+            return 0;           
+    }
+    
+    if (descr->type != 'c' && descr->type != '[' && descr->type != 'n')
+        while (isspace(UCHAR(str[pos])))
+            ++pos;
+    
+    scanned = pos - anchor;
+
+    
+    if (descr->type == 'n') {
+        
+        *valObjPtr = Jim_NewIntObj(interp, anchor + scanned);
+    }
+    else if (pos >= strLen) {
+        
+        return -1;
+    }
+    else if (descr->type == 'c') {
+            int c;
+            scanned += utf8_tounicode(&str[pos], &c);
+            *valObjPtr = Jim_NewIntObj(interp, c);
+            return scanned;
+    }
+    else {
+        
+        if (descr->width > 0) {
+            size_t sLen = utf8_strlen(&str[pos], strLen - pos);
+            size_t tLen = descr->width > sLen ? sLen : descr->width;
+
+            tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen);
+            tok = tmpObj->bytes;
+        }
+        else {
+            
+            tok = &str[pos];
+        }
+        switch (descr->type) {
+            case 'd':
+            case 'o':
+            case 'x':
+            case 'u':
+            case 'i':{
+                    char *endp; 
+                    jim_wide w;
+
+                    int base = descr->type == 'o' ? 8
+                        : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
+
+                    
+                    if (base == 0) {
+                        w = jim_strtoull(tok, &endp);
+                    }
+                    else {
+                        w = strtoull(tok, &endp, base);
+                    }
+
+                    if (endp != tok) {
+                        
+                        *valObjPtr = Jim_NewIntObj(interp, w);
+
+                        
+                        scanned += endp - tok;
+                    }
+                    else {
+                        scanned = *tok ? 0 : -1;
+                    }
+                    break;
+                }
+            case 's':
+            case '[':{
+                    *valObjPtr = JimScanAString(interp, descr->arg, tok);
+                    scanned += Jim_Length(*valObjPtr);
+                    break;
+                }
+            case 'e':
+            case 'f':
+            case 'g':{
+                    char *endp;
+                    double value = strtod(tok, &endp);
+
+                    if (endp != tok) {
+                        
+                        *valObjPtr = Jim_NewDoubleObj(interp, value);
+                        
+                        scanned += endp - tok;
+                    }
+                    else {
+                        scanned = *tok ? 0 : -1;
+                    }
+                    break;
+                }
+        }
+        if (tmpObj) {
+            Jim_FreeNewObj(interp, tmpObj);
+        }
+    }
+    return scanned;
+}
+
+
+Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags)
+{
+    size_t i, pos;
+    int scanned = 1;
+    const char *str = Jim_String(strObjPtr);
+    int strLen = Jim_Utf8Length(interp, strObjPtr);
+    Jim_Obj *resultList = 0;
+    Jim_Obj **resultVec = 0;
+    int resultc;
+    Jim_Obj *emptyStr = 0;
+    ScanFmtStringObj *fmtObj;
+
+    
+    JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format"));
+
+    fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr;
+    
+    if (fmtObj->error != 0) {
+        if (flags & JIM_ERRMSG)
+            Jim_SetResultString(interp, fmtObj->error, -1);
+        return 0;
+    }
+    
+    emptyStr = Jim_NewEmptyStringObj(interp);
+    Jim_IncrRefCount(emptyStr);
+    
+    resultList = Jim_NewListObj(interp, NULL, 0);
+    if (fmtObj->maxPos > 0) {
+        for (i = 0; i < fmtObj->maxPos; ++i)
+            Jim_ListAppendElement(interp, resultList, emptyStr);
+        JimListGetElements(interp, resultList, &resultc, &resultVec);
+    }
+    
+    for (i = 0, pos = 0; i < fmtObj->count; ++i) {
+        ScanFmtPartDescr *descr = &(fmtObj->descr[i]);
+        Jim_Obj *value = 0;
+
+        
+        if (descr->type == 0)
+            continue;
+        
+        if (scanned > 0)
+            scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value);
+        
+        if (scanned == -1 && i == 0)
+            goto eof;
+        
+        pos += scanned;
+
+        
+        if (value == 0)
+            value = Jim_NewEmptyStringObj(interp);
+        
+        if (descr->pos == -1) {
+            Jim_FreeNewObj(interp, value);
+        }
+        else if (descr->pos == 0)
+            
+            Jim_ListAppendElement(interp, resultList, value);
+        else if (resultVec[descr->pos - 1] == emptyStr) {
+            
+            Jim_DecrRefCount(interp, resultVec[descr->pos - 1]);
+            Jim_IncrRefCount(value);
+            resultVec[descr->pos - 1] = value;
+        }
+        else {
+            
+            Jim_FreeNewObj(interp, value);
+            goto err;
+        }
+    }
+    Jim_DecrRefCount(interp, emptyStr);
+    return resultList;
+  eof:
+    Jim_DecrRefCount(interp, emptyStr);
+    Jim_FreeNewObj(interp, resultList);
+    return (Jim_Obj *)EOF;
+  err:
+    Jim_DecrRefCount(interp, emptyStr);
+    Jim_FreeNewObj(interp, resultList);
+    return 0;
+}
+
+
+static void JimPrngInit(Jim_Interp *interp)
+{
+#define PRNG_SEED_SIZE 256
+    int i;
+    unsigned int *seed;
+    time_t t = time(NULL);
+
+    interp->prngState = Jim_Alloc(sizeof(Jim_PrngState));
+
+    seed = Jim_Alloc(PRNG_SEED_SIZE * sizeof(*seed));
+    for (i = 0; i < PRNG_SEED_SIZE; i++) {
+        seed[i] = (rand() ^ t ^ clock());
+    }
+    JimPrngSeed(interp, (unsigned char *)seed, PRNG_SEED_SIZE * sizeof(*seed));
+    Jim_Free(seed);
+}
+
+
+static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len)
+{
+    Jim_PrngState *prng;
+    unsigned char *destByte = (unsigned char *)dest;
+    unsigned int si, sj, x;
+
+    
+    if (interp->prngState == NULL)
+        JimPrngInit(interp);
+    prng = interp->prngState;
+    
+    for (x = 0; x < len; x++) {
+        prng->i = (prng->i + 1) & 0xff;
+        si = prng->sbox[prng->i];
+        prng->j = (prng->j + si) & 0xff;
+        sj = prng->sbox[prng->j];
+        prng->sbox[prng->i] = sj;
+        prng->sbox[prng->j] = si;
+        *destByte++ = prng->sbox[(si + sj) & 0xff];
+    }
+}
+
+
+static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen)
+{
+    int i;
+    Jim_PrngState *prng;
+
+    
+    if (interp->prngState == NULL)
+        JimPrngInit(interp);
+    prng = interp->prngState;
+
+    
+    for (i = 0; i < 256; i++)
+        prng->sbox[i] = i;
+    
+    for (i = 0; i < seedLen; i++) {
+        unsigned char t;
+
+        t = prng->sbox[i & 0xFF];
+        prng->sbox[i & 0xFF] = prng->sbox[seed[i]];
+        prng->sbox[seed[i]] = t;
+    }
+    prng->i = prng->j = 0;
+
+    for (i = 0; i < 256; i += seedLen) {
+        JimRandomBytes(interp, seed, seedLen);
+    }
+}
+
+
+static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    jim_wide wideValue, increment = 1;
+    Jim_Obj *intObjPtr;
+
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "varName ?increment?");
+        return JIM_ERR;
+    }
+    if (argc == 3) {
+        if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK)
+            return JIM_ERR;
+    }
+    intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
+    if (!intObjPtr) {
+        
+        wideValue = 0;
+    }
+    else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) {
+        return JIM_ERR;
+    }
+    if (!intObjPtr || Jim_IsShared(intObjPtr)) {
+        intObjPtr = Jim_NewIntObj(interp, wideValue + increment);
+        if (Jim_SetVariable(interp, argv[1], intObjPtr) != JIM_OK) {
+            Jim_FreeNewObj(interp, intObjPtr);
+            return JIM_ERR;
+        }
+    }
+    else {
+        
+        Jim_InvalidateStringRep(intObjPtr);
+        JimWideValue(intObjPtr) = wideValue + increment;
+
+        if (argv[1]->typePtr != &variableObjType) {
+            
+            Jim_SetVariable(interp, argv[1], intObjPtr);
+        }
+    }
+    Jim_SetResult(interp, intObjPtr);
+    return JIM_OK;
+}
+
+
+#define JIM_EVAL_SARGV_LEN 8    
+#define JIM_EVAL_SINTV_LEN 8    
+
+
+static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int retcode;
+
+    if (interp->unknown_called > 50) {
+        return JIM_ERR;
+    }
+
+
+    
+    if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
+        return JIM_ERR;
+
+    interp->unknown_called++;
+    
+    retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
+    interp->unknown_called--;
+
+    return retcode;
+}
+
+static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
+{
+    int retcode;
+    Jim_Cmd *cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
+
+    if (cmdPtr == NULL) {
+        return JimUnknown(interp, objc, objv);
+    }
+    if (interp->evalDepth == interp->maxEvalDepth) {
+        Jim_SetResultString(interp, "Infinite eval recursion", -1);
+        return JIM_ERR;
+    }
+    interp->evalDepth++;
+
+    
+    JimIncrCmdRefCount(cmdPtr);
+    Jim_SetEmptyResult(interp);
+    if (cmdPtr->isproc) {
+        retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
+    }
+    else {
+        interp->cmdPrivData = cmdPtr->u.native.privData;
+        retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
+    }
+    JimDecrCmdRefCount(interp, cmdPtr);
+    interp->evalDepth--;
+
+    return retcode;
+}
+
+int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
+{
+    int i, retcode;
+
+    
+    for (i = 0; i < objc; i++)
+        Jim_IncrRefCount(objv[i]);
+
+    retcode = JimInvokeCommand(interp, objc, objv);
+
+    
+    for (i = 0; i < objc; i++)
+        Jim_DecrRefCount(interp, objv[i]);
+
+    return retcode;
+}
+
+int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv)
+{
+    int ret;
+    Jim_Obj **nargv = Jim_Alloc((objc + 1) * sizeof(*nargv));
+
+    nargv[0] = prefix;
+    memcpy(&nargv[1], &objv[0], sizeof(nargv[0]) * objc);
+    ret = Jim_EvalObjVector(interp, objc + 1, nargv);
+    Jim_Free(nargv);
+    return ret;
+}
+
+static void JimAddErrorToStack(Jim_Interp *interp, int retcode, ScriptObj *script)
+{
+    int rc = retcode;
+
+    if (rc == JIM_ERR && !interp->errorFlag) {
+        
+        interp->errorFlag = 1;
+        Jim_IncrRefCount(script->fileNameObj);
+        Jim_DecrRefCount(interp, interp->errorFileNameObj);
+        interp->errorFileNameObj = script->fileNameObj;
+        interp->errorLine = script->linenr;
+
+        JimResetStackTrace(interp);
+        
+        interp->addStackTrace++;
+    }
+
+    
+    if (rc == JIM_ERR && interp->addStackTrace > 0) {
+        
+
+        JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
+
+        if (Jim_Length(script->fileNameObj)) {
+            interp->addStackTrace = 0;
+        }
+
+        Jim_DecrRefCount(interp, interp->errorProc);
+        interp->errorProc = interp->emptyObj;
+        Jim_IncrRefCount(interp->errorProc);
+    }
+    else if (rc == JIM_RETURN && interp->returnCode == JIM_ERR) {
+        
+    }
+    else {
+        interp->addStackTrace = 0;
+    }
+}
+
+static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr)
+{
+    Jim_Obj *objPtr;
+
+    switch (token->type) {
+        case JIM_TT_STR:
+        case JIM_TT_ESC:
+            objPtr = token->objPtr;
+            break;
+        case JIM_TT_VAR:
+            objPtr = Jim_GetVariable(interp, token->objPtr, JIM_ERRMSG);
+            break;
+        case JIM_TT_DICTSUGAR:
+            objPtr = JimExpandDictSugar(interp, token->objPtr);
+            break;
+        case JIM_TT_EXPRSUGAR:
+            objPtr = JimExpandExprSugar(interp, token->objPtr);
+            break;
+        case JIM_TT_CMD:
+            switch (Jim_EvalObj(interp, token->objPtr)) {
+                case JIM_OK:
+                case JIM_RETURN:
+                    objPtr = interp->result;
+                    break;
+                case JIM_BREAK:
+                    
+                    return JIM_BREAK;
+                case JIM_CONTINUE:
+                    
+                    return JIM_CONTINUE;
+                default:
+                    return JIM_ERR;
+            }
+            break;
+        default:
+            JimPanic((1,
+                "default token type (%d) reached " "in Jim_SubstObj().", token->type));
+            objPtr = NULL;
+            break;
+    }
+    if (objPtr) {
+        *objPtrPtr = objPtr;
+        return JIM_OK;
+    }
+    return JIM_ERR;
+}
+
+static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags)
+{
+    int totlen = 0, i;
+    Jim_Obj **intv;
+    Jim_Obj *sintv[JIM_EVAL_SINTV_LEN];
+    Jim_Obj *objPtr;
+    char *s;
+
+    if (tokens <= JIM_EVAL_SINTV_LEN)
+        intv = sintv;
+    else
+        intv = Jim_Alloc(sizeof(Jim_Obj *) * tokens);
+
+    for (i = 0; i < tokens; i++) {
+        switch (JimSubstOneToken(interp, &token[i], &intv[i])) {
+            case JIM_OK:
+            case JIM_RETURN:
+                break;
+            case JIM_BREAK:
+                if (flags & JIM_SUBST_FLAG) {
+                    
+                    tokens = i;
+                    continue;
+                }
+                
+                
+            case JIM_CONTINUE:
+                if (flags & JIM_SUBST_FLAG) {
+                    intv[i] = NULL;
+                    continue;
+                }
+                
+                
+            default:
+                while (i--) {
+                    Jim_DecrRefCount(interp, intv[i]);
+                }
+                if (intv != sintv) {
+                    Jim_Free(intv);
+                }
+                return NULL;
+        }
+        Jim_IncrRefCount(intv[i]);
+        Jim_String(intv[i]);
+        totlen += intv[i]->length;
+    }
+
+    
+    if (tokens == 1 && intv[0] && intv == sintv) {
+        Jim_DecrRefCount(interp, intv[0]);
+        return intv[0];
+    }
+
+    objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
+
+    if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
+        && token[2].type == JIM_TT_VAR) {
+        
+        objPtr->typePtr = &interpolatedObjType;
+        objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
+        objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
+        Jim_IncrRefCount(intv[2]);
+    }
+
+    s = objPtr->bytes = Jim_Alloc(totlen + 1);
+    objPtr->length = totlen;
+    for (i = 0; i < tokens; i++) {
+        if (intv[i]) {
+            memcpy(s, intv[i]->bytes, intv[i]->length);
+            s += intv[i]->length;
+            Jim_DecrRefCount(interp, intv[i]);
+        }
+    }
+    objPtr->bytes[totlen] = '\0';
+    
+    if (intv != sintv) {
+        Jim_Free(intv);
+    }
+
+    return objPtr;
+}
+
+
+static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
+{
+    int retcode = JIM_OK;
+
+    if (listPtr->internalRep.listValue.len) {
+        Jim_IncrRefCount(listPtr);
+        retcode = JimInvokeCommand(interp,
+            listPtr->internalRep.listValue.len,
+            listPtr->internalRep.listValue.ele);
+        Jim_DecrRefCount(interp, listPtr);
+    }
+    return retcode;
+}
+
+int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
+{
+    SetListFromAny(interp, listPtr);
+    return JimEvalObjList(interp, listPtr);
+}
+
+int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
+{
+    int i;
+    ScriptObj *script;
+    ScriptToken *token;
+    int retcode = JIM_OK;
+    Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL;
+    Jim_Obj *prevScriptObj;
+
+    if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
+        return JimEvalObjList(interp, scriptObjPtr);
+    }
+
+    Jim_IncrRefCount(scriptObjPtr);     
+    script = Jim_GetScript(interp, scriptObjPtr);
+
+    Jim_SetEmptyResult(interp);
+
+    token = script->token;
+
+#ifdef JIM_OPTIMIZATION
+    if (script->len == 0) {
+        Jim_DecrRefCount(interp, scriptObjPtr);
+        return JIM_OK;
+    }
+    if (script->len == 3
+        && token[1].objPtr->typePtr == &commandObjType
+        && token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0
+        && token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand
+        && token[2].objPtr->typePtr == &variableObjType) {
+
+        Jim_Obj *objPtr = Jim_GetVariable(interp, token[2].objPtr, JIM_NONE);
+
+        if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
+            JimWideValue(objPtr)++;
+            Jim_InvalidateStringRep(objPtr);
+            Jim_DecrRefCount(interp, scriptObjPtr);
+            Jim_SetResult(interp, objPtr);
+            return JIM_OK;
+        }
+    }
+#endif
+
+    script->inUse++;
+
+    
+    prevScriptObj = interp->currentScriptObj;
+    interp->currentScriptObj = scriptObjPtr;
+
+    interp->errorFlag = 0;
+    argv = sargv;
+
+    for (i = 0; i < script->len && retcode == JIM_OK; ) {
+        int argc;
+        int j;
+
+        
+        argc = token[i].objPtr->internalRep.scriptLineValue.argc;
+        script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
+
+        
+        if (argc > JIM_EVAL_SARGV_LEN)
+            argv = Jim_Alloc(sizeof(Jim_Obj *) * argc);
+
+        
+        i++;
+
+        for (j = 0; j < argc; j++) {
+            long wordtokens = 1;
+            int expand = 0;
+            Jim_Obj *wordObjPtr = NULL;
+
+            if (token[i].type == JIM_TT_WORD) {
+                wordtokens = JimWideValue(token[i++].objPtr);
+                if (wordtokens < 0) {
+                    expand = 1;
+                    wordtokens = -wordtokens;
+                }
+            }
+
+            if (wordtokens == 1) {
+
+                switch (token[i].type) {
+                    case JIM_TT_ESC:
+                    case JIM_TT_STR:
+                        wordObjPtr = token[i].objPtr;
+                        break;
+                    case JIM_TT_VAR:
+                        wordObjPtr = Jim_GetVariable(interp, token[i].objPtr, JIM_ERRMSG);
+                        break;
+                    case JIM_TT_EXPRSUGAR:
+                        wordObjPtr = JimExpandExprSugar(interp, token[i].objPtr);
+                        break;
+                    case JIM_TT_DICTSUGAR:
+                        wordObjPtr = JimExpandDictSugar(interp, token[i].objPtr);
+                        break;
+                    case JIM_TT_CMD:
+                        retcode = Jim_EvalObj(interp, token[i].objPtr);
+                        if (retcode == JIM_OK) {
+                            wordObjPtr = Jim_GetResult(interp);
+                        }
+                        break;
+                    default:
+                        JimPanic((1, "default token type reached " "in Jim_EvalObj()."));
+                }
+            }
+            else {
+                wordObjPtr = JimInterpolateTokens(interp, token + i, wordtokens, JIM_NONE);
+            }
+
+            if (!wordObjPtr) {
+                if (retcode == JIM_OK) {
+                    retcode = JIM_ERR;
+                }
+                break;
+            }
+
+            Jim_IncrRefCount(wordObjPtr);
+            i += wordtokens;
+
+            if (!expand) {
+                argv[j] = wordObjPtr;
+            }
+            else {
+                
+                int len = Jim_ListLength(interp, wordObjPtr);
+                int newargc = argc + len - 1;
+                int k;
+
+                if (len > 1) {
+                    if (argv == sargv) {
+                        if (newargc > JIM_EVAL_SARGV_LEN) {
+                            argv = Jim_Alloc(sizeof(*argv) * newargc);
+                            memcpy(argv, sargv, sizeof(*argv) * j);
+                        }
+                    }
+                    else {
+                        
+                        argv = Jim_Realloc(argv, sizeof(*argv) * newargc);
+                    }
+                }
+
+                
+                for (k = 0; k < len; k++) {
+                    argv[j++] = wordObjPtr->internalRep.listValue.ele[k];
+                    Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]);
+                }
+
+                Jim_DecrRefCount(interp, wordObjPtr);
+
+                
+                j--;
+                argc += len - 1;
+            }
+        }
+
+        if (retcode == JIM_OK && argc) {
+            
+            retcode = JimInvokeCommand(interp, argc, argv);
+            
+            if (Jim_CheckSignal(interp)) {
+                retcode = JIM_SIGNAL;
+            }
+        }
+
+        
+        while (j-- > 0) {
+            Jim_DecrRefCount(interp, argv[j]);
+        }
+
+        if (argv != sargv) {
+            Jim_Free(argv);
+            argv = sargv;
+        }
+    }
+
+    
+    JimAddErrorToStack(interp, retcode, script);
+
+    
+    interp->currentScriptObj = prevScriptObj;
+
+    Jim_FreeIntRep(interp, scriptObjPtr);
+    scriptObjPtr->typePtr = &scriptObjType;
+    Jim_SetIntRepPtr(scriptObjPtr, script);
+    Jim_DecrRefCount(interp, scriptObjPtr);
+
+    return retcode;
+}
+
+static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj)
+{
+    int retcode;
+    
+    const char *varname = Jim_String(argNameObj);
+    if (*varname == '&') {
+        
+        Jim_Obj *objPtr;
+        Jim_CallFrame *savedCallFrame = interp->framePtr;
+
+        interp->framePtr = interp->framePtr->parent;
+        objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
+        interp->framePtr = savedCallFrame;
+        if (!objPtr) {
+            return JIM_ERR;
+        }
+
+        
+        objPtr = Jim_NewStringObj(interp, varname + 1, -1);
+        Jim_IncrRefCount(objPtr);
+        retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
+        Jim_DecrRefCount(interp, objPtr);
+    }
+    else {
+        retcode = Jim_SetVariable(interp, argNameObj, argValObj);
+    }
+    return retcode;
+}
+
+static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
+{
+    
+    Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
+    int i;
+
+    for (i = 0; i < cmd->u.proc.argListLen; i++) {
+        Jim_AppendString(interp, argmsg, " ", 1);
+
+        if (i == cmd->u.proc.argsPos) {
+            if (cmd->u.proc.arglist[i].defaultObjPtr) {
+                
+                Jim_AppendString(interp, argmsg, "?", 1);
+                Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
+                Jim_AppendString(interp, argmsg, " ...?", -1);
+            }
+            else {
+                
+                Jim_AppendString(interp, argmsg, "?arg...?", -1);
+            }
+        }
+        else {
+            if (cmd->u.proc.arglist[i].defaultObjPtr) {
+                Jim_AppendString(interp, argmsg, "?", 1);
+                Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr);
+                Jim_AppendString(interp, argmsg, "?", 1);
+            }
+            else {
+                const char *arg = Jim_String(cmd->u.proc.arglist[i].nameObjPtr);
+                if (*arg == '&') {
+                    arg++;
+                }
+                Jim_AppendString(interp, argmsg, arg, -1);
+            }
+        }
+    }
+    Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
+    Jim_FreeNewObj(interp, argmsg);
+}
+
+#ifdef jim_ext_namespace
+int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
+{
+    Jim_CallFrame *callFramePtr;
+    int retcode;
+
+    
+    callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
+    callFramePtr->argv = &interp->emptyObj;
+    callFramePtr->argc = 0;
+    callFramePtr->procArgsObjPtr = NULL;
+    callFramePtr->procBodyObjPtr = scriptObj;
+    callFramePtr->staticVars = NULL;
+    callFramePtr->fileNameObj = interp->emptyObj;
+    callFramePtr->line = 0;
+    Jim_IncrRefCount(scriptObj);
+    interp->framePtr = callFramePtr;
+
+    
+    if (interp->framePtr->level == interp->maxCallFrameDepth) {
+        Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
+        retcode = JIM_ERR;
+    }
+    else {
+        
+        retcode = Jim_EvalObj(interp, scriptObj);
+    }
+
+    
+    interp->framePtr = interp->framePtr->parent;
+    if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
+        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
+    }
+    else {
+        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
+    }
+
+    return retcode;
+}
+#endif
+
+static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
+{
+    Jim_CallFrame *callFramePtr;
+    int i, d, retcode, optargs;
+    Jim_Stack *localCommands;
+    ScriptObj *script;
+
+    
+    if (argc - 1 < cmd->u.proc.reqArity ||
+        (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) {
+        JimSetProcWrongArgs(interp, argv[0], cmd);
+        return JIM_ERR;
+    }
+
+    if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
+        
+        return JIM_OK;
+    }
+
+    
+    if (interp->framePtr->level == interp->maxCallFrameDepth) {
+        Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
+        return JIM_ERR;
+    }
+
+    
+    callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
+    callFramePtr->argv = argv;
+    callFramePtr->argc = argc;
+    callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
+    callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
+    callFramePtr->staticVars = cmd->u.proc.staticVars;
+
+    
+    script = Jim_GetScript(interp, interp->currentScriptObj);
+    callFramePtr->fileNameObj = script->fileNameObj;
+    callFramePtr->line = script->linenr;
+
+    Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
+    Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
+    interp->framePtr = callFramePtr;
+
+    
+    optargs = (argc - 1 - cmd->u.proc.reqArity);
+
+    
+    i = 1;
+    for (d = 0; d < cmd->u.proc.argListLen; d++) {
+        Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr;
+        if (d == cmd->u.proc.argsPos) {
+            
+            Jim_Obj *listObjPtr;
+            int argsLen = 0;
+            if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) {
+                argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity);
+            }
+            listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen);
+
+            
+            if (cmd->u.proc.arglist[d].defaultObjPtr) {
+                nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr;
+            }
+            retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr);
+            if (retcode != JIM_OK) {
+                goto badargset;
+            }
+
+            i += argsLen;
+            continue;
+        }
+
+        
+        if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) {
+            retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]);
+        }
+        else {
+            
+            retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr);
+        }
+        if (retcode != JIM_OK) {
+            goto badargset;
+        }
+    }
+
+    
+    retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
+
+badargset:
+    
+    
+    localCommands = callFramePtr->localCommands;
+    callFramePtr->localCommands = NULL;
+
+    interp->framePtr = interp->framePtr->parent;
+    if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
+        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
+    }
+    else {
+        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
+    }
+
+    
+    while (retcode == JIM_EVAL) {
+        Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
+
+        Jim_IncrRefCount(resultScriptObjPtr);
+        
+        JimPanic((!Jim_IsList(resultScriptObjPtr), "tailcall (JIM_EVAL) returned non-list"));
+
+        retcode = JimEvalObjList(interp, resultScriptObjPtr);
+        if (retcode == JIM_RETURN) {
+            interp->returnLevel++;
+        }
+        Jim_DecrRefCount(interp, resultScriptObjPtr);
+    }
+    
+    if (retcode == JIM_RETURN) {
+        if (--interp->returnLevel <= 0) {
+            retcode = interp->returnCode;
+            interp->returnCode = JIM_OK;
+            interp->returnLevel = 0;
+        }
+    }
+    else if (retcode == JIM_ERR) {
+        interp->addStackTrace++;
+        Jim_DecrRefCount(interp, interp->errorProc);
+        interp->errorProc = argv[0];
+        Jim_IncrRefCount(interp->errorProc);
+    }
+
+    
+    JimDeleteLocalProcs(interp, localCommands);
+
+    return retcode;
+}
+
+int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
+{
+    int retval;
+    Jim_Obj *scriptObjPtr;
+
+    scriptObjPtr = Jim_NewStringObj(interp, script, -1);
+    Jim_IncrRefCount(scriptObjPtr);
+
+    if (filename) {
+        Jim_Obj *prevScriptObj;
+
+        JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno);
+
+        prevScriptObj = interp->currentScriptObj;
+        interp->currentScriptObj = scriptObjPtr;
+
+        retval = Jim_EvalObj(interp, scriptObjPtr);
+
+        interp->currentScriptObj = prevScriptObj;
+    }
+    else {
+        retval = Jim_EvalObj(interp, scriptObjPtr);
+    }
+    Jim_DecrRefCount(interp, scriptObjPtr);
+    return retval;
+}
+
+int Jim_Eval(Jim_Interp *interp, const char *script)
+{
+    return Jim_EvalObj(interp, Jim_NewStringObj(interp, script, -1));
+}
+
+
+int Jim_EvalGlobal(Jim_Interp *interp, const char *script)
+{
+    int retval;
+    Jim_CallFrame *savedFramePtr = interp->framePtr;
+
+    interp->framePtr = interp->topFramePtr;
+    retval = Jim_Eval(interp, script);
+    interp->framePtr = savedFramePtr;
+
+    return retval;
+}
+
+int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename)
+{
+    int retval;
+    Jim_CallFrame *savedFramePtr = interp->framePtr;
+
+    interp->framePtr = interp->topFramePtr;
+    retval = Jim_EvalFile(interp, filename);
+    interp->framePtr = savedFramePtr;
+
+    return retval;
+}
+
+#include <sys/stat.h>
+
+int Jim_EvalFile(Jim_Interp *interp, const char *filename)
+{
+    FILE *fp;
+    char *buf;
+    Jim_Obj *scriptObjPtr;
+    Jim_Obj *prevScriptObj;
+    struct stat sb;
+    int retcode;
+    int readlen;
+    struct JimParseResult result;
+
+    if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
+        Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
+        return JIM_ERR;
+    }
+    if (sb.st_size == 0) {
+        fclose(fp);
+        return JIM_OK;
+    }
+
+    buf = Jim_Alloc(sb.st_size + 1);
+    readlen = fread(buf, 1, sb.st_size, fp);
+    if (ferror(fp)) {
+        fclose(fp);
+        Jim_Free(buf);
+        Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno));
+        return JIM_ERR;
+    }
+    fclose(fp);
+    buf[readlen] = 0;
+
+    scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
+    JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
+    Jim_IncrRefCount(scriptObjPtr);
+
+    
+    if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
+        const char *msg;
+        char linebuf[20];
+
+        switch (result.missing) {
+            case '[':
+                msg = "unmatched \"[\"";
+                break;
+            case '{':
+                msg = "missing close-brace";
+                break;
+            case '"':
+            default:
+                msg = "missing quote";
+                break;
+        }
+
+        snprintf(linebuf, sizeof(linebuf), "%d", result.line);
+
+        Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
+            msg, filename, linebuf);
+        Jim_DecrRefCount(interp, scriptObjPtr);
+        return JIM_ERR;
+    }
+
+    prevScriptObj = interp->currentScriptObj;
+    interp->currentScriptObj = scriptObjPtr;
+
+    retcode = Jim_EvalObj(interp, scriptObjPtr);
+
+    
+    if (retcode == JIM_RETURN) {
+        if (--interp->returnLevel <= 0) {
+            retcode = interp->returnCode;
+            interp->returnCode = JIM_OK;
+            interp->returnLevel = 0;
+        }
+    }
+    if (retcode == JIM_ERR) {
+        
+        interp->addStackTrace++;
+    }
+
+    interp->currentScriptObj = prevScriptObj;
+
+    Jim_DecrRefCount(interp, scriptObjPtr);
+
+    return retcode;
+}
+
+static void JimParseSubst(struct JimParserCtx *pc, int flags)
+{
+    pc->tstart = pc->p;
+    pc->tline = pc->linenr;
+
+    if (pc->len == 0) {
+        pc->tend = pc->p;
+        pc->tt = JIM_TT_EOL;
+        pc->eof = 1;
+        return;
+    }
+    if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) {
+        JimParseCmd(pc);
+        return;
+    }
+    if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
+        if (JimParseVar(pc) == JIM_OK) {
+            return;
+        }
+        
+        pc->tstart = pc->p;
+        flags |= JIM_SUBST_NOVAR;
+    }
+    while (pc->len) {
+        if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
+            break;
+        }
+        if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) {
+            break;
+        }
+        if (*pc->p == '\\' && pc->len > 1) {
+            pc->p++;
+            pc->len--;
+        }
+        pc->p++;
+        pc->len--;
+    }
+    pc->tend = pc->p - 1;
+    pc->tt = (flags & JIM_SUBST_NOESC) ? JIM_TT_STR : JIM_TT_ESC;
+}
+
+
+static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags)
+{
+    int scriptTextLen;
+    const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
+    struct JimParserCtx parser;
+    struct ScriptObj *script = Jim_Alloc(sizeof(*script));
+    ParseTokenList tokenlist;
+
+    
+    ScriptTokenListInit(&tokenlist);
+
+    JimParserInit(&parser, scriptText, scriptTextLen, 1);
+    while (1) {
+        JimParseSubst(&parser, flags);
+        if (parser.eof) {
+            
+            break;
+        }
+        ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
+            parser.tline);
+    }
+
+    
+    script->inUse = 1;
+    script->substFlags = flags;
+    script->fileNameObj = interp->emptyObj;
+    Jim_IncrRefCount(script->fileNameObj);
+    SubstObjAddTokens(interp, script, &tokenlist);
+
+    
+    ScriptTokenListFree(&tokenlist);
+
+#ifdef DEBUG_SHOW_SUBST
+    {
+        int i;
+
+        printf("==== Subst ====\n");
+        for (i = 0; i < script->len; i++) {
+            printf("[%2d] %s '%s'\n", i, jim_tt_name(script->token[i].type),
+                Jim_String(script->token[i].objPtr));
+        }
+    }
+#endif
+
+    
+    Jim_FreeIntRep(interp, objPtr);
+    Jim_SetIntRepPtr(objPtr, script);
+    objPtr->typePtr = &scriptObjType;
+    return JIM_OK;
+}
+
+static ScriptObj *Jim_GetSubst(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
+{
+    if (objPtr->typePtr != &scriptObjType || ((ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags != flags)
+        SetSubstFromAny(interp, objPtr, flags);
+    return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
+}
+
+int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags)
+{
+    ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags);
+
+    Jim_IncrRefCount(substObjPtr);      
+    script->inUse++;
+
+    *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags);
+
+    script->inUse--;
+    Jim_DecrRefCount(interp, substObjPtr);
+    if (*resObjPtrPtr == NULL) {
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
+{
+    Jim_Obj *objPtr;
+    Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc);
+
+    if (*msg) {
+        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
+    }
+    Jim_IncrRefCount(listObjPtr);
+    objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
+    Jim_DecrRefCount(interp, listObjPtr);
+
+    Jim_IncrRefCount(objPtr);
+    Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
+    Jim_DecrRefCount(interp, objPtr);
+}
+
+typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
+    Jim_HashEntry *he, int type);
+
+#define JimTrivialMatch(pattern)       (strpbrk((pattern), "*[?\\") == NULL)
+
+static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
+    JimHashtableIteratorCallbackType *callback, int type)
+{
+    Jim_HashEntry *he;
+    Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
+
+    
+    if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
+        he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
+        if (he) {
+            callback(interp, listObjPtr, he, type);
+        }
+    }
+    else {
+        Jim_HashTableIterator htiter;
+        JimInitHashTableIterator(ht, &htiter);
+        while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+            if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
+                callback(interp, listObjPtr, he, type);
+            }
+        }
+    }
+    return listObjPtr;
+}
+
+
+#define JIM_CMDLIST_COMMANDS 0
+#define JIM_CMDLIST_PROCS 1
+#define JIM_CMDLIST_CHANNELS 2
+
+static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
+    Jim_HashEntry *he, int type)
+{
+    Jim_Cmd *cmdPtr = (Jim_Cmd *)he->u.val;
+    Jim_Obj *objPtr;
+
+    if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
+        
+        return;
+    }
+
+    objPtr = Jim_NewStringObj(interp, he->key, -1);
+    Jim_IncrRefCount(objPtr);
+
+    if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, objPtr)) {
+        Jim_ListAppendElement(interp, listObjPtr, objPtr);
+    }
+    Jim_DecrRefCount(interp, objPtr);
+}
+
+
+static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type)
+{
+    return JimHashtablePatternMatch(interp, &interp->commands, patternObjPtr, JimCommandMatch, type);
+}
+
+
+#define JIM_VARLIST_GLOBALS 0
+#define JIM_VARLIST_LOCALS 1
+#define JIM_VARLIST_VARS 2
+
+#define JIM_VARLIST_VALUES 0x1000
+
+static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
+    Jim_HashEntry *he, int type)
+{
+    Jim_Var *varPtr = (Jim_Var *)he->u.val;
+
+    if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
+        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
+        if (type & JIM_VARLIST_VALUES) {
+            Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
+        }
+    }
+}
+
+
+static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode)
+{
+    if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) {
+        return interp->emptyObj;
+    }
+    else {
+        Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr;
+        return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, mode);
+    }
+}
+
+static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr,
+    Jim_Obj **objPtrPtr, int info_level_cmd)
+{
+    Jim_CallFrame *targetCallFrame;
+
+    targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr);
+    if (targetCallFrame == NULL) {
+        return JIM_ERR;
+    }
+    
+    if (targetCallFrame == interp->topFramePtr) {
+        Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr);
+        return JIM_ERR;
+    }
+    if (info_level_cmd) {
+        *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc);
+    }
+    else {
+        Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
+
+        Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]);
+        Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj);
+        Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line));
+        *objPtrPtr = listObj;
+    }
+    return JIM_OK;
+}
+
+
+
+static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "?-nonewline? string");
+        return JIM_ERR;
+    }
+    if (argc == 3) {
+        if (!Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) {
+            Jim_SetResultString(interp, "The second argument must " "be -nonewline", -1);
+            return JIM_ERR;
+        }
+        else {
+            fputs(Jim_String(argv[2]), stdout);
+        }
+    }
+    else {
+        puts(Jim_String(argv[1]));
+    }
+    return JIM_OK;
+}
+
+
+static int JimAddMulHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op)
+{
+    jim_wide wideValue, res;
+    double doubleValue, doubleRes;
+    int i;
+
+    res = (op == JIM_EXPROP_ADD) ? 0 : 1;
+
+    for (i = 1; i < argc; i++) {
+        if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK)
+            goto trydouble;
+        if (op == JIM_EXPROP_ADD)
+            res += wideValue;
+        else
+            res *= wideValue;
+    }
+    Jim_SetResultInt(interp, res);
+    return JIM_OK;
+  trydouble:
+    doubleRes = (double)res;
+    for (; i < argc; i++) {
+        if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK)
+            return JIM_ERR;
+        if (op == JIM_EXPROP_ADD)
+            doubleRes += doubleValue;
+        else
+            doubleRes *= doubleValue;
+    }
+    Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes));
+    return JIM_OK;
+}
+
+
+static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op)
+{
+    jim_wide wideValue, res = 0;
+    double doubleValue, doubleRes = 0;
+    int i = 2;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "number ?number ... number?");
+        return JIM_ERR;
+    }
+    else if (argc == 2) {
+        if (Jim_GetWide(interp, argv[1], &wideValue) != JIM_OK) {
+            if (Jim_GetDouble(interp, argv[1], &doubleValue) != JIM_OK) {
+                return JIM_ERR;
+            }
+            else {
+                if (op == JIM_EXPROP_SUB)
+                    doubleRes = -doubleValue;
+                else
+                    doubleRes = 1.0 / doubleValue;
+                Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes));
+                return JIM_OK;
+            }
+        }
+        if (op == JIM_EXPROP_SUB) {
+            res = -wideValue;
+            Jim_SetResultInt(interp, res);
+        }
+        else {
+            doubleRes = 1.0 / wideValue;
+            Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes));
+        }
+        return JIM_OK;
+    }
+    else {
+        if (Jim_GetWide(interp, argv[1], &res) != JIM_OK) {
+            if (Jim_GetDouble(interp, argv[1], &doubleRes)
+                != JIM_OK) {
+                return JIM_ERR;
+            }
+            else {
+                goto trydouble;
+            }
+        }
+    }
+    for (i = 2; i < argc; i++) {
+        if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) {
+            doubleRes = (double)res;
+            goto trydouble;
+        }
+        if (op == JIM_EXPROP_SUB)
+            res -= wideValue;
+        else
+            res /= wideValue;
+    }
+    Jim_SetResultInt(interp, res);
+    return JIM_OK;
+  trydouble:
+    for (; i < argc; i++) {
+        if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK)
+            return JIM_ERR;
+        if (op == JIM_EXPROP_SUB)
+            doubleRes -= doubleValue;
+        else
+            doubleRes /= doubleValue;
+    }
+    Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes));
+    return JIM_OK;
+}
+
+
+
+static int Jim_AddCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_ADD);
+}
+
+
+static int Jim_MulCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_MUL);
+}
+
+
+static int Jim_SubCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_SUB);
+}
+
+
+static int Jim_DivCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_DIV);
+}
+
+
+static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "varName ?newValue?");
+        return JIM_ERR;
+    }
+    if (argc == 2) {
+        Jim_Obj *objPtr;
+
+        objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
+        if (!objPtr)
+            return JIM_ERR;
+        Jim_SetResult(interp, objPtr);
+        return JIM_OK;
+    }
+    
+    if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
+        return JIM_ERR;
+    Jim_SetResult(interp, argv[2]);
+    return JIM_OK;
+}
+
+static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int i = 1;
+    int complain = 1;
+
+    while (i < argc) {
+        if (Jim_CompareStringImmediate(interp, argv[i], "--")) {
+            i++;
+            break;
+        }
+        if (Jim_CompareStringImmediate(interp, argv[i], "-nocomplain")) {
+            complain = 0;
+            i++;
+            continue;
+        }
+        break;
+    }
+
+    while (i < argc) {
+        if (Jim_UnsetVariable(interp, argv[i], complain ? JIM_ERRMSG : JIM_NONE) != JIM_OK
+            && complain) {
+            return JIM_ERR;
+        }
+        i++;
+    }
+    return JIM_OK;
+}
+
+
+static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "condition body");
+        return JIM_ERR;
+    }
+
+    
+    while (1) {
+        int boolean, retval;
+
+        if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK)
+            return retval;
+        if (!boolean)
+            break;
+
+        if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) {
+            switch (retval) {
+                case JIM_BREAK:
+                    goto out;
+                    break;
+                case JIM_CONTINUE:
+                    continue;
+                    break;
+                default:
+                    return retval;
+            }
+        }
+    }
+  out:
+    Jim_SetEmptyResult(interp);
+    return JIM_OK;
+}
+
+
+static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int retval;
+    int boolean = 1;
+    Jim_Obj *varNamePtr = NULL;
+    Jim_Obj *stopVarNamePtr = NULL;
+
+    if (argc != 5) {
+        Jim_WrongNumArgs(interp, 1, argv, "start test next body");
+        return JIM_ERR;
+    }
+
+    
+    if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
+        return retval;
+    }
+
+    retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
+
+
+#ifdef JIM_OPTIMIZATION
+    if (retval == JIM_OK && boolean) {
+        ScriptObj *incrScript;
+        ExprByteCode *expr;
+        jim_wide stop, currentVal;
+        Jim_Obj *objPtr;
+        int cmpOffset;
+
+        
+        expr = JimGetExpression(interp, argv[2]);
+        incrScript = Jim_GetScript(interp, argv[3]);
+
+        
+        if (incrScript->len != 3 || !expr || expr->len != 3) {
+            goto evalstart;
+        }
+        
+        if (incrScript->token[1].type != JIM_TT_ESC ||
+            expr->token[0].type != JIM_TT_VAR ||
+            (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) {
+            goto evalstart;
+        }
+
+        if (expr->token[2].type == JIM_EXPROP_LT) {
+            cmpOffset = 0;
+        }
+        else if (expr->token[2].type == JIM_EXPROP_LTE) {
+            cmpOffset = 1;
+        }
+        else {
+            goto evalstart;
+        }
+
+        
+        if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) {
+            goto evalstart;
+        }
+
+        
+        if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) {
+            goto evalstart;
+        }
+
+        
+        if (expr->token[1].type == JIM_TT_EXPR_INT) {
+            if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) {
+                goto evalstart;
+            }
+        }
+        else {
+            stopVarNamePtr = expr->token[1].objPtr;
+            Jim_IncrRefCount(stopVarNamePtr);
+            
+            stop = 0;
+        }
+
+        
+        varNamePtr = expr->token[0].objPtr;
+        Jim_IncrRefCount(varNamePtr);
+
+        objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE);
+        if (objPtr == NULL || Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK) {
+            goto testcond;
+        }
+
+        
+        while (retval == JIM_OK) {
+            
+            
+
+            
+            if (stopVarNamePtr) {
+                objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE);
+                if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) {
+                    goto testcond;
+                }
+            }
+
+            if (currentVal >= stop + cmpOffset) {
+                break;
+            }
+
+            
+            retval = Jim_EvalObj(interp, argv[4]);
+            if (retval == JIM_OK || retval == JIM_CONTINUE) {
+                retval = JIM_OK;
+
+                objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
+
+                
+                if (objPtr == NULL) {
+                    retval = JIM_ERR;
+                    goto out;
+                }
+                if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
+                    currentVal = ++JimWideValue(objPtr);
+                    Jim_InvalidateStringRep(objPtr);
+                }
+                else {
+                    if (Jim_GetWide(interp, objPtr, &currentVal) != JIM_OK ||
+                        Jim_SetVariable(interp, varNamePtr, Jim_NewIntObj(interp,
+                                ++currentVal)) != JIM_OK) {
+                        goto evalnext;
+                    }
+                }
+            }
+        }
+        goto out;
+    }
+  evalstart:
+#endif
+
+    while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) {
+        
+        retval = Jim_EvalObj(interp, argv[4]);
+
+        if (retval == JIM_OK || retval == JIM_CONTINUE) {
+            
+          evalnext:
+            retval = Jim_EvalObj(interp, argv[3]);
+            if (retval == JIM_OK || retval == JIM_CONTINUE) {
+                
+              testcond:
+                retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean);
+            }
+        }
+    }
+  out:
+    if (stopVarNamePtr) {
+        Jim_DecrRefCount(interp, stopVarNamePtr);
+    }
+    if (varNamePtr) {
+        Jim_DecrRefCount(interp, varNamePtr);
+    }
+
+    if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) {
+        Jim_SetEmptyResult(interp);
+        return JIM_OK;
+    }
+
+    return retval;
+}
+
+
+static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int retval;
+    jim_wide i;
+    jim_wide limit;
+    jim_wide incr = 1;
+    Jim_Obj *bodyObjPtr;
+
+    if (argc != 5 && argc != 6) {
+        Jim_WrongNumArgs(interp, 1, argv, "var first limit ?incr? body");
+        return JIM_ERR;
+    }
+
+    if (Jim_GetWide(interp, argv[2], &i) != JIM_OK ||
+        Jim_GetWide(interp, argv[3], &limit) != JIM_OK ||
+          (argc == 6 && Jim_GetWide(interp, argv[4], &incr) != JIM_OK)) {
+        return JIM_ERR;
+    }
+    bodyObjPtr = (argc == 5) ? argv[4] : argv[5];
+
+    retval = Jim_SetVariable(interp, argv[1], argv[2]);
+
+    while (((i < limit && incr > 0) || (i > limit && incr < 0)) && retval == JIM_OK) {
+        retval = Jim_EvalObj(interp, bodyObjPtr);
+        if (retval == JIM_OK || retval == JIM_CONTINUE) {
+            Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
+
+            retval = JIM_OK;
+
+            
+            i += incr;
+
+            if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
+                if (argv[1]->typePtr != &variableObjType) {
+                    if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
+                        return JIM_ERR;
+                    }
+                }
+                JimWideValue(objPtr) = i;
+                Jim_InvalidateStringRep(objPtr);
+
+                if (argv[1]->typePtr != &variableObjType) {
+                    if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
+                        retval = JIM_ERR;
+                        break;
+                    }
+                }
+            }
+            else {
+                objPtr = Jim_NewIntObj(interp, i);
+                retval = Jim_SetVariable(interp, argv[1], objPtr);
+                if (retval != JIM_OK) {
+                    Jim_FreeNewObj(interp, objPtr);
+                }
+            }
+        }
+    }
+
+    if (retval == JIM_OK || retval == JIM_CONTINUE || retval == JIM_BREAK) {
+        Jim_SetEmptyResult(interp);
+        return JIM_OK;
+    }
+    return retval;
+}
+
+typedef struct {
+    Jim_Obj *objPtr;
+    int idx;
+} Jim_ListIter;
+
+static void JimListIterInit(Jim_ListIter *iter, Jim_Obj *objPtr)
+{
+    iter->objPtr = objPtr;
+    iter->idx = 0;
+}
+
+static Jim_Obj *JimListIterNext(Jim_Interp *interp, Jim_ListIter *iter)
+{
+    if (iter->idx >= Jim_ListLength(interp, iter->objPtr)) {
+        return NULL;
+    }
+    return iter->objPtr->internalRep.listValue.ele[iter->idx++];
+}
+
+static int JimListIterDone(Jim_Interp *interp, Jim_ListIter *iter)
+{
+    return iter->idx >= Jim_ListLength(interp, iter->objPtr);
+}
+
+
+static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
+{
+    int result = JIM_ERR;
+    int i, numargs;
+    Jim_ListIter twoiters[2];   
+    Jim_ListIter *iters;
+    Jim_Obj *script;
+    Jim_Obj *resultObj;
+
+    if (argc < 4 || argc % 2 != 0) {
+        Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
+        return JIM_ERR;
+    }
+    script = argv[argc - 1];    
+    numargs = (argc - 1 - 1);    
+
+    if (numargs == 2) {
+        iters = twoiters;
+    }
+    else {
+        iters = Jim_Alloc(numargs * sizeof(*iters));
+    }
+    for (i = 0; i < numargs; i++) {
+        JimListIterInit(&iters[i], argv[i + 1]);
+        if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
+            Jim_SetResultString(interp, "foreach varlist is empty", -1);
+            return JIM_ERR;
+        }
+    }
+
+    if (doMap) {
+        resultObj = Jim_NewListObj(interp, NULL, 0);
+    }
+    else {
+        resultObj = interp->emptyObj;
+    }
+    Jim_IncrRefCount(resultObj);
+
+    while (1) {
+        
+        for (i = 0; i < numargs; i += 2) {
+            if (!JimListIterDone(interp, &iters[i + 1])) {
+                break;
+            }
+        }
+        if (i == numargs) {
+            
+            break;
+        }
+
+        
+        for (i = 0; i < numargs; i += 2) {
+            Jim_Obj *varName;
+
+            
+            JimListIterInit(&iters[i], argv[i + 1]);
+            while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
+                Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
+                if (!valObj) {
+                    
+                    valObj = interp->emptyObj;
+                }
+                
+                Jim_IncrRefCount(valObj);
+                result = Jim_SetVariable(interp, varName, valObj);
+                Jim_DecrRefCount(interp, valObj);
+                if (result != JIM_OK) {
+                    goto err;
+                }
+            }
+        }
+        switch (result = Jim_EvalObj(interp, script)) {
+            case JIM_OK:
+                if (doMap) {
+                    Jim_ListAppendElement(interp, resultObj, interp->result);
+                }
+                break;
+            case JIM_CONTINUE:
+                break;
+            case JIM_BREAK:
+                goto out;
+            default:
+                goto err;
+        }
+    }
+  out:
+    result = JIM_OK;
+    Jim_SetResult(interp, resultObj);
+  err:
+    Jim_DecrRefCount(interp, resultObj);
+    if (numargs > 2) {
+        Jim_Free(iters);
+    }
+    return result;
+}
+
+
+static int Jim_ForeachCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return JimForeachMapHelper(interp, argc, argv, 0);
+}
+
+
+static int Jim_LmapCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return JimForeachMapHelper(interp, argc, argv, 1);
+}
+
+
+static int Jim_LassignCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int result = JIM_ERR;
+    int i;
+    Jim_ListIter iter;
+    Jim_Obj *resultObj;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "varList list ?varName ...?");
+        return JIM_ERR;
+    }
+
+    JimListIterInit(&iter, argv[1]);
+
+    for (i = 2; i < argc; i++) {
+        Jim_Obj *valObj = JimListIterNext(interp, &iter);
+        result = Jim_SetVariable(interp, argv[i], valObj ? valObj : interp->emptyObj);
+        if (result != JIM_OK) {
+            return result;
+        }
+    }
+
+    resultObj = Jim_NewListObj(interp, NULL, 0);
+    while (!JimListIterDone(interp, &iter)) {
+        Jim_ListAppendElement(interp, resultObj, JimListIterNext(interp, &iter));
+    }
+
+    Jim_SetResult(interp, resultObj);
+
+    return JIM_OK;
+}
+
+
+static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int boolean, retval, current = 1, falsebody = 0;
+
+    if (argc >= 3) {
+        while (1) {
+            
+            if (current >= argc)
+                goto err;
+            if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
+                != JIM_OK)
+                return retval;
+            
+            if (current >= argc)
+                goto err;
+            if (Jim_CompareStringImmediate(interp, argv[current], "then"))
+                current++;
+            
+            if (current >= argc)
+                goto err;
+            if (boolean)
+                return Jim_EvalObj(interp, argv[current]);
+            
+            if (++current >= argc) {
+                Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+                return JIM_OK;
+            }
+            falsebody = current++;
+            if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
+                
+                if (current != argc - 1)
+                    goto err;
+                return Jim_EvalObj(interp, argv[current]);
+            }
+            else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
+                continue;
+            
+            else if (falsebody != argc - 1)
+                goto err;
+            return Jim_EvalObj(interp, argv[falsebody]);
+        }
+        return JIM_OK;
+    }
+  err:
+    Jim_WrongNumArgs(interp, 1, argv, "condition ?then? trueBody ?elseif ...? ?else? falseBody");
+    return JIM_ERR;
+}
+
+
+
+int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj,
+    Jim_Obj *stringObj, int nocase)
+{
+    Jim_Obj *parms[4];
+    int argc = 0;
+    long eq;
+    int rc;
+
+    parms[argc++] = commandObj;
+    if (nocase) {
+        parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1);
+    }
+    parms[argc++] = patternObj;
+    parms[argc++] = stringObj;
+
+    rc = Jim_EvalObjVector(interp, argc, parms);
+
+    if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) {
+        eq = -rc;
+    }
+
+    return eq;
+}
+
+enum
+{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD };
+
+
+static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int matchOpt = SWITCH_EXACT, opt = 1, patCount, i;
+    Jim_Obj *command = 0, *const *caseList = 0, *strObj;
+    Jim_Obj *script = 0;
+
+    if (argc < 3) {
+      wrongnumargs:
+        Jim_WrongNumArgs(interp, 1, argv, "?options? string "
+            "pattern body ... ?default body?   or   " "{pattern body ?pattern body ...?}");
+        return JIM_ERR;
+    }
+    for (opt = 1; opt < argc; ++opt) {
+        const char *option = Jim_String(argv[opt]);
+
+        if (*option != '-')
+            break;
+        else if (strncmp(option, "--", 2) == 0) {
+            ++opt;
+            break;
+        }
+        else if (strncmp(option, "-exact", 2) == 0)
+            matchOpt = SWITCH_EXACT;
+        else if (strncmp(option, "-glob", 2) == 0)
+            matchOpt = SWITCH_GLOB;
+        else if (strncmp(option, "-regexp", 2) == 0)
+            matchOpt = SWITCH_RE;
+        else if (strncmp(option, "-command", 2) == 0) {
+            matchOpt = SWITCH_CMD;
+            if ((argc - opt) < 2)
+                goto wrongnumargs;
+            command = argv[++opt];
+        }
+        else {
+            Jim_SetResultFormatted(interp,
+                "bad option \"%#s\": must be -exact, -glob, -regexp, -command procname or --",
+                argv[opt]);
+            return JIM_ERR;
+        }
+        if ((argc - opt) < 2)
+            goto wrongnumargs;
+    }
+    strObj = argv[opt++];
+    patCount = argc - opt;
+    if (patCount == 1) {
+        Jim_Obj **vector;
+
+        JimListGetElements(interp, argv[opt], &patCount, &vector);
+        caseList = vector;
+    }
+    else
+        caseList = &argv[opt];
+    if (patCount == 0 || patCount % 2 != 0)
+        goto wrongnumargs;
+    for (i = 0; script == 0 && i < patCount; i += 2) {
+        Jim_Obj *patObj = caseList[i];
+
+        if (!Jim_CompareStringImmediate(interp, patObj, "default")
+            || i < (patCount - 2)) {
+            switch (matchOpt) {
+                case SWITCH_EXACT:
+                    if (Jim_StringEqObj(strObj, patObj))
+                        script = caseList[i + 1];
+                    break;
+                case SWITCH_GLOB:
+                    if (Jim_StringMatchObj(interp, patObj, strObj, 0))
+                        script = caseList[i + 1];
+                    break;
+                case SWITCH_RE:
+                    command = Jim_NewStringObj(interp, "regexp", -1);
+                    
+                case SWITCH_CMD:{
+                        int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0);
+
+                        if (argc - opt == 1) {
+                            Jim_Obj **vector;
+
+                            JimListGetElements(interp, argv[opt], &patCount, &vector);
+                            caseList = vector;
+                        }
+                        
+                        if (rc < 0) {
+                            return -rc;
+                        }
+                        if (rc)
+                            script = caseList[i + 1];
+                        break;
+                    }
+            }
+        }
+        else {
+            script = caseList[i + 1];
+        }
+    }
+    for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2)
+        script = caseList[i + 1];
+    if (script && Jim_CompareStringImmediate(interp, script, "-")) {
+        Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]);
+        return JIM_ERR;
+    }
+    Jim_SetEmptyResult(interp);
+    if (script) {
+        return Jim_EvalObj(interp, script);
+    }
+    return JIM_OK;
+}
+
+
+static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *listObjPtr;
+
+    listObjPtr = Jim_NewListObj(interp, argv + 1, argc - 1);
+    Jim_SetResult(interp, listObjPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr, *listObjPtr;
+    int i;
+    int idx;
+
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
+        return JIM_ERR;
+    }
+    objPtr = argv[1];
+    Jim_IncrRefCount(objPtr);
+    for (i = 2; i < argc; i++) {
+        listObjPtr = objPtr;
+        if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) {
+            Jim_DecrRefCount(interp, listObjPtr);
+            return JIM_ERR;
+        }
+        if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) {
+            Jim_DecrRefCount(interp, listObjPtr);
+            Jim_SetEmptyResult(interp);
+            return JIM_OK;
+        }
+        Jim_IncrRefCount(objPtr);
+        Jim_DecrRefCount(interp, listObjPtr);
+    }
+    Jim_SetResult(interp, objPtr);
+    Jim_DecrRefCount(interp, objPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "list");
+        return JIM_ERR;
+    }
+    Jim_SetResultInt(interp, Jim_ListLength(interp, argv[1]));
+    return JIM_OK;
+}
+
+
+static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    static const char * const options[] = {
+        "-bool", "-not", "-nocase", "-exact", "-glob", "-regexp", "-all", "-inline", "-command",
+            NULL
+    };
+    enum
+    { OPT_BOOL, OPT_NOT, OPT_NOCASE, OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_ALL, OPT_INLINE,
+            OPT_COMMAND };
+    int i;
+    int opt_bool = 0;
+    int opt_not = 0;
+    int opt_nocase = 0;
+    int opt_all = 0;
+    int opt_inline = 0;
+    int opt_match = OPT_EXACT;
+    int listlen;
+    int rc = JIM_OK;
+    Jim_Obj *listObjPtr = NULL;
+    Jim_Obj *commandObj = NULL;
+
+    if (argc < 3) {
+      wrongargs:
+        Jim_WrongNumArgs(interp, 1, argv,
+            "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? list value");
+        return JIM_ERR;
+    }
+
+    for (i = 1; i < argc - 2; i++) {
+        int option;
+
+        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
+            return JIM_ERR;
+        }
+        switch (option) {
+            case OPT_BOOL:
+                opt_bool = 1;
+                opt_inline = 0;
+                break;
+            case OPT_NOT:
+                opt_not = 1;
+                break;
+            case OPT_NOCASE:
+                opt_nocase = 1;
+                break;
+            case OPT_INLINE:
+                opt_inline = 1;
+                opt_bool = 0;
+                break;
+            case OPT_ALL:
+                opt_all = 1;
+                break;
+            case OPT_COMMAND:
+                if (i >= argc - 2) {
+                    goto wrongargs;
+                }
+                commandObj = argv[++i];
+                
+            case OPT_EXACT:
+            case OPT_GLOB:
+            case OPT_REGEXP:
+                opt_match = option;
+                break;
+        }
+    }
+
+    argv += i;
+
+    if (opt_all) {
+        listObjPtr = Jim_NewListObj(interp, NULL, 0);
+    }
+    if (opt_match == OPT_REGEXP) {
+        commandObj = Jim_NewStringObj(interp, "regexp", -1);
+    }
+    if (commandObj) {
+        Jim_IncrRefCount(commandObj);
+    }
+
+    listlen = Jim_ListLength(interp, argv[0]);
+    for (i = 0; i < listlen; i++) {
+        Jim_Obj *objPtr;
+        int eq = 0;
+
+        Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
+        switch (opt_match) {
+            case OPT_EXACT:
+                eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
+                break;
+
+            case OPT_GLOB:
+                eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase);
+                break;
+
+            case OPT_REGEXP:
+            case OPT_COMMAND:
+                eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase);
+                if (eq < 0) {
+                    if (listObjPtr) {
+                        Jim_FreeNewObj(interp, listObjPtr);
+                    }
+                    rc = JIM_ERR;
+                    goto done;
+                }
+                break;
+        }
+
+        
+        if (!eq && opt_bool && opt_not && !opt_all) {
+            continue;
+        }
+
+        if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) {
+            
+            Jim_Obj *resultObj;
+
+            if (opt_bool) {
+                resultObj = Jim_NewIntObj(interp, eq ^ opt_not);
+            }
+            else if (!opt_inline) {
+                resultObj = Jim_NewIntObj(interp, i);
+            }
+            else {
+                resultObj = objPtr;
+            }
+
+            if (opt_all) {
+                Jim_ListAppendElement(interp, listObjPtr, resultObj);
+            }
+            else {
+                Jim_SetResult(interp, resultObj);
+                goto done;
+            }
+        }
+    }
+
+    if (opt_all) {
+        Jim_SetResult(interp, listObjPtr);
+    }
+    else {
+        
+        if (opt_bool) {
+            Jim_SetResultBool(interp, opt_not);
+        }
+        else if (!opt_inline) {
+            Jim_SetResultInt(interp, -1);
+        }
+    }
+
+  done:
+    if (commandObj) {
+        Jim_DecrRefCount(interp, commandObj);
+    }
+    return rc;
+}
+
+
+static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *listObjPtr;
+    int shared, i;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
+        return JIM_ERR;
+    }
+    listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
+    if (!listObjPtr) {
+        
+        listObjPtr = Jim_NewListObj(interp, NULL, 0);
+        if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) {
+            Jim_FreeNewObj(interp, listObjPtr);
+            return JIM_ERR;
+        }
+    }
+    shared = Jim_IsShared(listObjPtr);
+    if (shared)
+        listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
+    for (i = 2; i < argc; i++)
+        Jim_ListAppendElement(interp, listObjPtr, argv[i]);
+    if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) {
+        if (shared)
+            Jim_FreeNewObj(interp, listObjPtr);
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, listObjPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int idx, len;
+    Jim_Obj *listPtr;
+
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "list index ?element ...?");
+        return JIM_ERR;
+    }
+    listPtr = argv[1];
+    if (Jim_IsShared(listPtr))
+        listPtr = Jim_DuplicateObj(interp, listPtr);
+    if (Jim_GetIndex(interp, argv[2], &idx) != JIM_OK)
+        goto err;
+    len = Jim_ListLength(interp, listPtr);
+    if (idx >= len)
+        idx = len;
+    else if (idx < 0)
+        idx = len + idx + 1;
+    Jim_ListInsertElements(interp, listPtr, idx, argc - 3, &argv[3]);
+    Jim_SetResult(interp, listPtr);
+    return JIM_OK;
+  err:
+    if (listPtr != argv[1]) {
+        Jim_FreeNewObj(interp, listPtr);
+    }
+    return JIM_ERR;
+}
+
+
+static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int first, last, len, rangeLen;
+    Jim_Obj *listObj;
+    Jim_Obj *newListObj;
+
+    if (argc < 4) {
+        Jim_WrongNumArgs(interp, 1, argv, "list first last ?element ...?");
+        return JIM_ERR;
+    }
+    if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK ||
+        Jim_GetIndex(interp, argv[3], &last) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    listObj = argv[1];
+    len = Jim_ListLength(interp, listObj);
+
+    first = JimRelToAbsIndex(len, first);
+    last = JimRelToAbsIndex(len, last);
+    JimRelToAbsRange(len, &first, &last, &rangeLen);
+
+
+    
+    if (first < len) {
+        
+    }
+    else if (len == 0) {
+        
+        first = 0;
+    }
+    else {
+        Jim_SetResultString(interp, "list doesn't contain element ", -1);
+        Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]);
+        return JIM_ERR;
+    }
+
+    
+    newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
+
+    
+    ListInsertElements(newListObj, -1, argc - 4, argv + 4);
+
+    
+    ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
+
+    Jim_SetResult(interp, newListObj);
+    return JIM_OK;
+}
+
+
+static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal");
+        return JIM_ERR;
+    }
+    else if (argc == 3) {
+        if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
+            return JIM_ERR;
+        Jim_SetResult(interp, argv[2]);
+        return JIM_OK;
+    }
+    if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
+        == JIM_ERR)
+        return JIM_ERR;
+    return JIM_OK;
+}
+
+
+static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
+{
+    static const char * const options[] = {
+        "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
+    };
+    enum
+    { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
+    Jim_Obj *resObj;
+    int i;
+    int retCode;
+
+    struct lsort_info info;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "?options? list");
+        return JIM_ERR;
+    }
+
+    info.type = JIM_LSORT_ASCII;
+    info.order = 1;
+    info.indexed = 0;
+    info.command = NULL;
+    info.interp = interp;
+
+    for (i = 1; i < (argc - 1); i++) {
+        int option;
+
+        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
+            != JIM_OK)
+            return JIM_ERR;
+        switch (option) {
+            case OPT_ASCII:
+                info.type = JIM_LSORT_ASCII;
+                break;
+            case OPT_NOCASE:
+                info.type = JIM_LSORT_NOCASE;
+                break;
+            case OPT_INTEGER:
+                info.type = JIM_LSORT_INTEGER;
+                break;
+            case OPT_INCREASING:
+                info.order = 1;
+                break;
+            case OPT_DECREASING:
+                info.order = -1;
+                break;
+            case OPT_COMMAND:
+                if (i >= (argc - 2)) {
+                    Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
+                    return JIM_ERR;
+                }
+                info.type = JIM_LSORT_COMMAND;
+                info.command = argv[i + 1];
+                i++;
+                break;
+            case OPT_INDEX:
+                if (i >= (argc - 2)) {
+                    Jim_SetResultString(interp, "\"-index\" option must be followed by list index", -1);
+                    return JIM_ERR;
+                }
+                if (Jim_GetIndex(interp, argv[i + 1], &info.index) != JIM_OK) {
+                    return JIM_ERR;
+                }
+                info.indexed = 1;
+                i++;
+                break;
+        }
+    }
+    resObj = Jim_DuplicateObj(interp, argv[argc - 1]);
+    retCode = ListSortElements(interp, resObj, &info);
+    if (retCode == JIM_OK) {
+        Jim_SetResult(interp, resObj);
+    }
+    else {
+        Jim_FreeNewObj(interp, resObj);
+    }
+    return retCode;
+}
+
+
+static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *stringObjPtr;
+    int i;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
+        return JIM_ERR;
+    }
+    if (argc == 2) {
+        stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
+        if (!stringObjPtr)
+            return JIM_ERR;
+    }
+    else {
+        int freeobj = 0;
+        stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
+        if (!stringObjPtr) {
+            
+            stringObjPtr = Jim_NewEmptyStringObj(interp);
+            freeobj = 1;
+        }
+        else if (Jim_IsShared(stringObjPtr)) {
+            freeobj = 1;
+            stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr);
+        }
+        for (i = 2; i < argc; i++) {
+            Jim_AppendObj(interp, stringObjPtr, argv[i]);
+        }
+        if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) {
+            if (freeobj) {
+                Jim_FreeNewObj(interp, stringObjPtr);
+            }
+            return JIM_ERR;
+        }
+    }
+    Jim_SetResult(interp, stringObjPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+#if !defined(JIM_DEBUG_COMMAND)
+    Jim_SetResultString(interp, "unsupported", -1);
+    return JIM_ERR;
+#endif
+}
+
+
+static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int rc;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "script ?...?");
+        return JIM_ERR;
+    }
+
+    if (argc == 2) {
+        rc = Jim_EvalObj(interp, argv[1]);
+    }
+    else {
+        rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
+    }
+
+    if (rc == JIM_ERR) {
+        
+        interp->addStackTrace++;
+    }
+    return rc;
+}
+
+
+static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc >= 2) {
+        int retcode;
+        Jim_CallFrame *savedCallFrame, *targetCallFrame;
+        Jim_Obj *objPtr;
+        const char *str;
+
+        
+        savedCallFrame = interp->framePtr;
+
+        
+        str = Jim_String(argv[1]);
+        if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
+            targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
+            argc--;
+            argv++;
+        }
+        else {
+            targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
+        }
+        if (targetCallFrame == NULL) {
+            return JIM_ERR;
+        }
+        if (argc < 2) {
+            argv--;
+            Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
+            return JIM_ERR;
+        }
+        
+        interp->framePtr = targetCallFrame;
+        if (argc == 2) {
+            retcode = Jim_EvalObj(interp, argv[1]);
+        }
+        else {
+            objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
+            Jim_IncrRefCount(objPtr);
+            retcode = Jim_EvalObj(interp, objPtr);
+            Jim_DecrRefCount(interp, objPtr);
+        }
+        interp->framePtr = savedCallFrame;
+        return retcode;
+    }
+    else {
+        Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
+        return JIM_ERR;
+    }
+}
+
+
+static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *exprResultPtr;
+    int retcode;
+
+    if (argc == 2) {
+        retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr);
+    }
+    else if (argc > 2) {
+        Jim_Obj *objPtr;
+
+        objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
+        Jim_IncrRefCount(objPtr);
+        retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr);
+        Jim_DecrRefCount(interp, objPtr);
+    }
+    else {
+        Jim_WrongNumArgs(interp, 1, argv, "expression ?...?");
+        return JIM_ERR;
+    }
+    if (retcode != JIM_OK)
+        return retcode;
+    Jim_SetResult(interp, exprResultPtr);
+    Jim_DecrRefCount(interp, exprResultPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 1) {
+        Jim_WrongNumArgs(interp, 1, argv, "");
+        return JIM_ERR;
+    }
+    return JIM_BREAK;
+}
+
+
+static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 1) {
+        Jim_WrongNumArgs(interp, 1, argv, "");
+        return JIM_ERR;
+    }
+    return JIM_CONTINUE;
+}
+
+
+static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int i;
+    Jim_Obj *stackTraceObj = NULL;
+    Jim_Obj *errorCodeObj = NULL;
+    int returnCode = JIM_OK;
+    long level = 1;
+
+    for (i = 1; i < argc - 1; i += 2) {
+        if (Jim_CompareStringImmediate(interp, argv[i], "-code")) {
+            if (Jim_GetReturnCode(interp, argv[i + 1], &returnCode) == JIM_ERR) {
+                return JIM_ERR;
+            }
+        }
+        else if (Jim_CompareStringImmediate(interp, argv[i], "-errorinfo")) {
+            stackTraceObj = argv[i + 1];
+        }
+        else if (Jim_CompareStringImmediate(interp, argv[i], "-errorcode")) {
+            errorCodeObj = argv[i + 1];
+        }
+        else if (Jim_CompareStringImmediate(interp, argv[i], "-level")) {
+            if (Jim_GetLong(interp, argv[i + 1], &level) != JIM_OK || level < 0) {
+                Jim_SetResultFormatted(interp, "bad level \"%#s\"", argv[i + 1]);
+                return JIM_ERR;
+            }
+        }
+        else {
+            break;
+        }
+    }
+
+    if (i != argc - 1 && i != argc) {
+        Jim_WrongNumArgs(interp, 1, argv,
+            "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
+    }
+
+    
+    if (stackTraceObj && returnCode == JIM_ERR) {
+        JimSetStackTrace(interp, stackTraceObj);
+    }
+    
+    if (errorCodeObj && returnCode == JIM_ERR) {
+        Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
+    }
+    interp->returnCode = returnCode;
+    interp->returnLevel = level;
+
+    if (i == argc - 1) {
+        Jim_SetResult(interp, argv[i]);
+    }
+    return JIM_RETURN;
+}
+
+
+static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_SetResult(interp, Jim_NewListObj(interp, argv + 1, argc - 1));
+    return JIM_EVAL;
+}
+
+static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *cmdList;
+    Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
+
+    
+    cmdList = Jim_DuplicateObj(interp, prefixListObj);
+    ListInsertElements(cmdList, -1, argc - 1, argv + 1);
+
+    return JimEvalObjList(interp, cmdList);
+}
+
+static void JimAliasCmdDelete(Jim_Interp *interp, void *privData)
+{
+    Jim_Obj *prefixListObj = privData;
+    Jim_DecrRefCount(interp, prefixListObj);
+}
+
+static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *prefixListObj;
+    const char *newname;
+
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "newname command ?args ...?");
+        return JIM_ERR;
+    }
+
+    prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2);
+    Jim_IncrRefCount(prefixListObj);
+    newname = Jim_String(argv[1]);
+    if (newname[0] == ':' && newname[1] == ':') {
+        while (*++newname == ':') {
+        }
+    }
+
+    Jim_SetResult(interp, argv[1]);
+
+    return Jim_CreateCommand(interp, newname, JimAliasCmd, prefixListObj, JimAliasCmdDelete);
+}
+
+
+static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Cmd *cmd;
+
+    if (argc != 4 && argc != 5) {
+        Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body");
+        return JIM_ERR;
+    }
+
+    if (JimValidName(interp, "procedure", argv[1]) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    if (argc == 4) {
+        cmd = JimCreateProcedureCmd(interp, argv[2], NULL, argv[3], NULL);
+    }
+    else {
+        cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
+    }
+
+    if (cmd) {
+        
+        Jim_Obj *qualifiedCmdNameObj;
+        const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
+
+        JimCreateCommand(interp, cmdname, cmd);
+
+        
+        JimUpdateProcNamespace(interp, cmd, cmdname);
+
+        JimFreeQualifiedName(interp, qualifiedCmdNameObj);
+
+        
+        Jim_SetResult(interp, argv[1]);
+        return JIM_OK;
+    }
+    return JIM_ERR;
+}
+
+
+static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int retcode;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
+        return JIM_ERR;
+    }
+
+    
+    interp->local++;
+    retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
+    interp->local--;
+
+
+    
+    if (retcode == 0) {
+        Jim_Obj *cmdNameObj = Jim_GetResult(interp);
+
+        if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
+            return JIM_ERR;
+        }
+        if (interp->framePtr->localCommands == NULL) {
+            interp->framePtr->localCommands = Jim_Alloc(sizeof(*interp->framePtr->localCommands));
+            Jim_InitStack(interp->framePtr->localCommands);
+        }
+        Jim_IncrRefCount(cmdNameObj);
+        Jim_StackPush(interp->framePtr->localCommands, cmdNameObj);
+    }
+
+    return retcode;
+}
+
+
+static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
+        return JIM_ERR;
+    }
+    else {
+        int retcode;
+
+        Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
+        if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
+            Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
+            return JIM_ERR;
+        }
+        
+        cmdPtr->u.proc.upcall++;
+        JimIncrCmdRefCount(cmdPtr);
+
+        
+        retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
+
+        
+        cmdPtr->u.proc.upcall--;
+        JimDecrCmdRefCount(interp, cmdPtr);
+
+        return retcode;
+    }
+}
+
+
+static int Jim_ApplyCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "lambdaExpr ?arg ...?");
+        return JIM_ERR;
+    }
+    else {
+        int ret;
+        Jim_Cmd *cmd;
+        Jim_Obj *argListObjPtr;
+        Jim_Obj *bodyObjPtr;
+        Jim_Obj *nsObj = NULL;
+        Jim_Obj **nargv;
+
+        int len = Jim_ListLength(interp, argv[1]);
+        if (len != 2 && len != 3) {
+            Jim_SetResultFormatted(interp, "can't interpret \"%#s\" as a lambda expression", argv[1]);
+            return JIM_ERR;
+        }
+
+        if (len == 3) {
+#ifdef jim_ext_namespace
+            
+            nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
+#else
+            Jim_SetResultString(interp, "namespaces not enabled", -1);
+            return JIM_ERR;
+#endif
+        }
+        argListObjPtr = Jim_ListGetIndex(interp, argv[1], 0);
+        bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
+
+        cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
+
+        if (cmd) {
+            
+            nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
+            nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
+            Jim_IncrRefCount(nargv[0]);
+            memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
+            ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
+            Jim_DecrRefCount(interp, nargv[0]);
+            Jim_Free(nargv);
+
+            JimDecrCmdRefCount(interp, cmd);
+            return ret;
+        }
+        return JIM_ERR;
+    }
+}
+
+
+
+static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_SetResult(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
+    return JIM_OK;
+}
+
+
+static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int i;
+    Jim_CallFrame *targetCallFrame;
+
+    
+    if (argc > 3 && (argc % 2 == 0)) {
+        targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
+        argc--;
+        argv++;
+    }
+    else {
+        targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
+    }
+    if (targetCallFrame == NULL) {
+        return JIM_ERR;
+    }
+
+    
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
+        return JIM_ERR;
+    }
+
+    
+    for (i = 1; i < argc; i += 2) {
+        if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK)
+            return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+
+static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int i;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
+        return JIM_ERR;
+    }
+    
+    if (interp->framePtr->level == 0)
+        return JIM_OK;          
+    for (i = 1; i < argc; i++) {
+        
+        const char *name = Jim_String(argv[i]);
+        if (name[0] != ':' || name[1] != ':') {
+            if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
+                return JIM_ERR;
+        }
+    }
+    return JIM_OK;
+}
+
+static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
+    Jim_Obj *objPtr, int nocase)
+{
+    int numMaps;
+    const char *str, *noMatchStart = NULL;
+    int strLen, i;
+    Jim_Obj *resultObjPtr;
+
+    numMaps = Jim_ListLength(interp, mapListObjPtr);
+    if (numMaps % 2) {
+        Jim_SetResultString(interp, "list must contain an even number of elements", -1);
+        return NULL;
+    }
+
+    str = Jim_String(objPtr);
+    strLen = Jim_Utf8Length(interp, objPtr);
+
+    
+    resultObjPtr = Jim_NewStringObj(interp, "", 0);
+    while (strLen) {
+        for (i = 0; i < numMaps; i += 2) {
+            Jim_Obj *objPtr;
+            const char *k;
+            int kl;
+
+            Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
+            k = Jim_String(objPtr);
+            kl = Jim_Utf8Length(interp, objPtr);
+
+            if (strLen >= kl && kl) {
+                int rc;
+                rc = JimStringCompareLen(str, k, kl, nocase);
+                if (rc == 0) {
+                    if (noMatchStart) {
+                        Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
+                        noMatchStart = NULL;
+                    }
+                    Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
+                    Jim_AppendObj(interp, resultObjPtr, objPtr);
+                    str += utf8_index(str, kl);
+                    strLen -= kl;
+                    break;
+                }
+            }
+        }
+        if (i == numMaps) {     
+            int c;
+            if (noMatchStart == NULL)
+                noMatchStart = str;
+            str += utf8_tounicode(str, &c);
+            strLen--;
+        }
+    }
+    if (noMatchStart) {
+        Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
+    }
+    return resultObjPtr;
+}
+
+
+static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int len;
+    int opt_case = 1;
+    int option;
+    static const char * const options[] = {
+        "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "replace",
+        "map", "repeat", "reverse", "index", "first", "last",
+        "trim", "trimleft", "trimright", "tolower", "toupper", "totitle", NULL
+    };
+    enum
+    {
+        OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_REPLACE,
+        OPT_MAP, OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST,
+        OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER, OPT_TOTITLE
+    };
+    static const char * const nocase_options[] = {
+        "-nocase", NULL
+    };
+    static const char * const nocase_length_options[] = {
+        "-nocase", "-length", NULL
+    };
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
+        return JIM_ERR;
+    }
+    if (Jim_GetEnum(interp, argv[1], options, &option, NULL,
+            JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
+        return JIM_ERR;
+
+    switch (option) {
+        case OPT_LENGTH:
+        case OPT_BYTELENGTH:
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "string");
+                return JIM_ERR;
+            }
+            if (option == OPT_LENGTH) {
+                len = Jim_Utf8Length(interp, argv[2]);
+            }
+            else {
+                len = Jim_Length(argv[2]);
+            }
+            Jim_SetResultInt(interp, len);
+            return JIM_OK;
+
+        case OPT_COMPARE:
+        case OPT_EQUAL:
+            {
+                
+                long opt_length = -1;
+                int n = argc - 4;
+                int i = 2;
+                while (n > 0) {
+                    int subopt;
+                    if (Jim_GetEnum(interp, argv[i++], nocase_length_options, &subopt, NULL,
+                            JIM_ENUM_ABBREV) != JIM_OK) {
+badcompareargs:
+                        Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
+                        return JIM_ERR;
+                    }
+                    if (subopt == 0) {
+                        
+                        opt_case = 0;
+                        n--;
+                    }
+                    else {
+                        
+                        if (n < 2) {
+                            goto badcompareargs;
+                        }
+                        if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
+                            return JIM_ERR;
+                        }
+                        n -= 2;
+                    }
+                }
+                if (n) {
+                    goto badcompareargs;
+                }
+                argv += argc - 2;
+                if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
+                    
+                    Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
+                }
+                else {
+                    if (opt_length >= 0) {
+                        n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
+                    }
+                    else {
+                        n = Jim_StringCompareObj(interp, argv[0], argv[1], !opt_case);
+                    }
+                    Jim_SetResultInt(interp, option == OPT_COMPARE ? n : n == 0);
+                }
+                return JIM_OK;
+            }
+
+        case OPT_MATCH:
+            if (argc != 4 &&
+                (argc != 5 ||
+                    Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL,
+                        JIM_ENUM_ABBREV) != JIM_OK)) {
+                Jim_WrongNumArgs(interp, 2, argv, "?-nocase? pattern string");
+                return JIM_ERR;
+            }
+            if (opt_case == 0) {
+                argv++;
+            }
+            Jim_SetResultBool(interp, Jim_StringMatchObj(interp, argv[2], argv[3], !opt_case));
+            return JIM_OK;
+
+        case OPT_MAP:{
+                Jim_Obj *objPtr;
+
+                if (argc != 4 &&
+                    (argc != 5 ||
+                        Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL,
+                            JIM_ENUM_ABBREV) != JIM_OK)) {
+                    Jim_WrongNumArgs(interp, 2, argv, "?-nocase? mapList string");
+                    return JIM_ERR;
+                }
+
+                if (opt_case == 0) {
+                    argv++;
+                }
+                objPtr = JimStringMap(interp, argv[2], argv[3], !opt_case);
+                if (objPtr == NULL) {
+                    return JIM_ERR;
+                }
+                Jim_SetResult(interp, objPtr);
+                return JIM_OK;
+            }
+
+        case OPT_RANGE:
+        case OPT_BYTERANGE:{
+                Jim_Obj *objPtr;
+
+                if (argc != 5) {
+                    Jim_WrongNumArgs(interp, 2, argv, "string first last");
+                    return JIM_ERR;
+                }
+                if (option == OPT_RANGE) {
+                    objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]);
+                }
+                else
+                {
+                    objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]);
+                }
+
+                if (objPtr == NULL) {
+                    return JIM_ERR;
+                }
+                Jim_SetResult(interp, objPtr);
+                return JIM_OK;
+            }
+
+        case OPT_REPLACE:{
+                Jim_Obj *objPtr;
+
+                if (argc != 5 && argc != 6) {
+                    Jim_WrongNumArgs(interp, 2, argv, "string first last ?string?");
+                    return JIM_ERR;
+                }
+                objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL);
+                if (objPtr == NULL) {
+                    return JIM_ERR;
+                }
+                Jim_SetResult(interp, objPtr);
+                return JIM_OK;
+            }
+
+
+        case OPT_REPEAT:{
+                Jim_Obj *objPtr;
+                jim_wide count;
+
+                if (argc != 4) {
+                    Jim_WrongNumArgs(interp, 2, argv, "string count");
+                    return JIM_ERR;
+                }
+                if (Jim_GetWide(interp, argv[3], &count) != JIM_OK) {
+                    return JIM_ERR;
+                }
+                objPtr = Jim_NewStringObj(interp, "", 0);
+                if (count > 0) {
+                    while (count--) {
+                        Jim_AppendObj(interp, objPtr, argv[2]);
+                    }
+                }
+                Jim_SetResult(interp, objPtr);
+                return JIM_OK;
+            }
+
+        case OPT_REVERSE:{
+                char *buf, *p;
+                const char *str;
+                int len;
+                int i;
+
+                if (argc != 3) {
+                    Jim_WrongNumArgs(interp, 2, argv, "string");
+                    return JIM_ERR;
+                }
+
+                str = Jim_GetString(argv[2], &len);
+                buf = Jim_Alloc(len + 1);
+                p = buf + len;
+                *p = 0;
+                for (i = 0; i < len; ) {
+                    int c;
+                    int l = utf8_tounicode(str, &c);
+                    memcpy(p - l, str, l);
+                    p -= l;
+                    i += l;
+                    str += l;
+                }
+                Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
+                return JIM_OK;
+            }
+
+        case OPT_INDEX:{
+                int idx;
+                const char *str;
+
+                if (argc != 4) {
+                    Jim_WrongNumArgs(interp, 2, argv, "string index");
+                    return JIM_ERR;
+                }
+                if (Jim_GetIndex(interp, argv[3], &idx) != JIM_OK) {
+                    return JIM_ERR;
+                }
+                str = Jim_String(argv[2]);
+                len = Jim_Utf8Length(interp, argv[2]);
+                if (idx != INT_MIN && idx != INT_MAX) {
+                    idx = JimRelToAbsIndex(len, idx);
+                }
+                if (idx < 0 || idx >= len || str == NULL) {
+                    Jim_SetResultString(interp, "", 0);
+                }
+                else if (len == Jim_Length(argv[2])) {
+                    
+                    Jim_SetResultString(interp, str + idx, 1);
+                }
+                else {
+                    int c;
+                    int i = utf8_index(str, idx);
+                    Jim_SetResultString(interp, str + i, utf8_tounicode(str + i, &c));
+                }
+                return JIM_OK;
+            }
+
+        case OPT_FIRST:
+        case OPT_LAST:{
+                int idx = 0, l1, l2;
+                const char *s1, *s2;
+
+                if (argc != 4 && argc != 5) {
+                    Jim_WrongNumArgs(interp, 2, argv, "subString string ?index?");
+                    return JIM_ERR;
+                }
+                s1 = Jim_String(argv[2]);
+                s2 = Jim_String(argv[3]);
+                l1 = Jim_Utf8Length(interp, argv[2]);
+                l2 = Jim_Utf8Length(interp, argv[3]);
+                if (argc == 5) {
+                    if (Jim_GetIndex(interp, argv[4], &idx) != JIM_OK) {
+                        return JIM_ERR;
+                    }
+                    idx = JimRelToAbsIndex(l2, idx);
+                }
+                else if (option == OPT_LAST) {
+                    idx = l2;
+                }
+                if (option == OPT_FIRST) {
+                    Jim_SetResultInt(interp, JimStringFirst(s1, l1, s2, l2, idx));
+                }
+                else {
+#ifdef JIM_UTF8
+                    Jim_SetResultInt(interp, JimStringLastUtf8(s1, l1, s2, idx));
+#else
+                    Jim_SetResultInt(interp, JimStringLast(s1, l1, s2, idx));
+#endif
+                }
+                return JIM_OK;
+            }
+
+        case OPT_TRIM:
+        case OPT_TRIMLEFT:
+        case OPT_TRIMRIGHT:{
+                Jim_Obj *trimchars;
+
+                if (argc != 3 && argc != 4) {
+                    Jim_WrongNumArgs(interp, 2, argv, "string ?trimchars?");
+                    return JIM_ERR;
+                }
+                trimchars = (argc == 4 ? argv[3] : NULL);
+                if (option == OPT_TRIM) {
+                    Jim_SetResult(interp, JimStringTrim(interp, argv[2], trimchars));
+                }
+                else if (option == OPT_TRIMLEFT) {
+                    Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], trimchars));
+                }
+                else if (option == OPT_TRIMRIGHT) {
+                    Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], trimchars));
+                }
+                return JIM_OK;
+            }
+
+        case OPT_TOLOWER:
+        case OPT_TOUPPER:
+        case OPT_TOTITLE:
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "string");
+                return JIM_ERR;
+            }
+            if (option == OPT_TOLOWER) {
+                Jim_SetResult(interp, JimStringToLower(interp, argv[2]));
+            }
+            else if (option == OPT_TOUPPER) {
+                Jim_SetResult(interp, JimStringToUpper(interp, argv[2]));
+            }
+            else {
+                Jim_SetResult(interp, JimStringToTitle(interp, argv[2]));
+            }
+            return JIM_OK;
+
+        case OPT_IS:
+            if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) {
+                return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5);
+            }
+            Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str");
+            return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+
+static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    long i, count = 1;
+    jim_wide start, elapsed;
+    char buf[60];
+    const char *fmt = "%" JIM_WIDE_MODIFIER " microseconds per iteration";
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "script ?count?");
+        return JIM_ERR;
+    }
+    if (argc == 3) {
+        if (Jim_GetLong(interp, argv[2], &count) != JIM_OK)
+            return JIM_ERR;
+    }
+    if (count < 0)
+        return JIM_OK;
+    i = count;
+    start = JimClock();
+    while (i-- > 0) {
+        int retval;
+
+        retval = Jim_EvalObj(interp, argv[1]);
+        if (retval != JIM_OK) {
+            return retval;
+        }
+    }
+    elapsed = JimClock() - start;
+    sprintf(buf, fmt, count == 0 ? 0 : elapsed / count);
+    Jim_SetResultString(interp, buf, -1);
+    return JIM_OK;
+}
+
+
+static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    long exitCode = 0;
+
+    if (argc > 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "?exitCode?");
+        return JIM_ERR;
+    }
+    if (argc == 2) {
+        if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK)
+            return JIM_ERR;
+    }
+    interp->exitCode = exitCode;
+    return JIM_EXIT;
+}
+
+
+static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int exitCode = 0;
+    int i;
+    int sig = 0;
+
+    
+    jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL);
+    static const int max_ignore_code = sizeof(ignore_mask) * 8;
+
+    Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1));
+
+    for (i = 1; i < argc - 1; i++) {
+        const char *arg = Jim_String(argv[i]);
+        jim_wide option;
+        int ignore;
+
+        
+        if (strcmp(arg, "--") == 0) {
+            i++;
+            break;
+        }
+        if (*arg != '-') {
+            break;
+        }
+
+        if (strncmp(arg, "-no", 3) == 0) {
+            arg += 3;
+            ignore = 1;
+        }
+        else {
+            arg++;
+            ignore = 0;
+        }
+
+        if (Jim_StringToWide(arg, &option, 10) != JIM_OK) {
+            option = -1;
+        }
+        if (option < 0) {
+            option = Jim_FindByName(arg, jimReturnCodes, jimReturnCodesSize);
+        }
+        if (option < 0) {
+            goto wrongargs;
+        }
+
+        if (ignore) {
+            ignore_mask |= (1 << option);
+        }
+        else {
+            ignore_mask &= ~(1 << option);
+        }
+    }
+
+    argc -= i;
+    if (argc < 1 || argc > 3) {
+      wrongargs:
+        Jim_WrongNumArgs(interp, 1, argv,
+            "?-?no?code ... --? script ?resultVarName? ?optionVarName?");
+        return JIM_ERR;
+    }
+    argv += i;
+
+    if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
+        sig++;
+    }
+
+    interp->signal_level += sig;
+    if (Jim_CheckSignal(interp)) {
+        
+        exitCode = JIM_SIGNAL;
+    }
+    else {
+        exitCode = Jim_EvalObj(interp, argv[0]);
+    }
+    interp->signal_level -= sig;
+
+    
+    if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
+        
+        return exitCode;
+    }
+
+    if (sig && exitCode == JIM_SIGNAL) {
+        
+        if (interp->signal_set_result) {
+            interp->signal_set_result(interp, interp->sigmask);
+        }
+        else {
+            Jim_SetResultInt(interp, interp->sigmask);
+        }
+        interp->sigmask = 0;
+    }
+
+    if (argc >= 2) {
+        if (Jim_SetVariable(interp, argv[1], Jim_GetResult(interp)) != JIM_OK) {
+            return JIM_ERR;
+        }
+        if (argc == 3) {
+            Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0);
+
+            Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1));
+            Jim_ListAppendElement(interp, optListObj,
+                Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode));
+            Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1));
+            Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel));
+            if (exitCode == JIM_ERR) {
+                Jim_Obj *errorCode;
+                Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo",
+                    -1));
+                Jim_ListAppendElement(interp, optListObj, interp->stackTrace);
+
+                errorCode = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE);
+                if (errorCode) {
+                    Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1));
+                    Jim_ListAppendElement(interp, optListObj, errorCode);
+                }
+            }
+            if (Jim_SetVariable(interp, argv[2], optListObj) != JIM_OK) {
+                return JIM_ERR;
+            }
+        }
+    }
+    Jim_SetResultInt(interp, exitCode);
+    return JIM_OK;
+}
+
+#ifdef JIM_REFERENCES
+
+
+static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 3 && argc != 4) {
+        Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?");
+        return JIM_ERR;
+    }
+    if (argc == 3) {
+        Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL));
+    }
+    else {
+        Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3]));
+    }
+    return JIM_OK;
+}
+
+
+static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Reference *refPtr;
+
+    if (argc != 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "reference");
+        return JIM_ERR;
+    }
+    if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
+        return JIM_ERR;
+    Jim_SetResult(interp, refPtr->objPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Reference *refPtr;
+
+    if (argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "reference newValue");
+        return JIM_ERR;
+    }
+    if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL)
+        return JIM_ERR;
+    Jim_IncrRefCount(argv[2]);
+    Jim_DecrRefCount(interp, refPtr->objPtr);
+    refPtr->objPtr = argv[2];
+    Jim_SetResult(interp, argv[2]);
+    return JIM_OK;
+}
+
+
+static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 1) {
+        Jim_WrongNumArgs(interp, 1, argv, "");
+        return JIM_ERR;
+    }
+    Jim_SetResultInt(interp, Jim_Collect(interp));
+
+    
+    while (interp->freeList) {
+        Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr;
+        Jim_Free(interp->freeList);
+        interp->freeList = nextObjPtr;
+    }
+
+    return JIM_OK;
+}
+
+
+static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?");
+        return JIM_ERR;
+    }
+    if (argc == 2) {
+        Jim_Obj *cmdNamePtr;
+
+        if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK)
+            return JIM_ERR;
+        if (cmdNamePtr != NULL) 
+            Jim_SetResult(interp, cmdNamePtr);
+    }
+    else {
+        if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK)
+            return JIM_ERR;
+        Jim_SetResult(interp, argv[2]);
+    }
+    return JIM_OK;
+}
+
+
+static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *listObjPtr;
+    Jim_HashTableIterator htiter;
+    Jim_HashEntry *he;
+
+    listObjPtr = Jim_NewListObj(interp, NULL, 0);
+
+    JimInitHashTableIterator(&interp->references, &htiter);
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        char buf[JIM_REFERENCE_SPACE + 1];
+        Jim_Reference *refPtr = he->u.val;
+        const unsigned long *refId = he->key;
+
+        JimFormatReference(buf, refPtr, *refId);
+        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
+    }
+    Jim_SetResult(interp, listObjPtr);
+    return JIM_OK;
+}
+#endif
+
+
+static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "oldName newName");
+        return JIM_ERR;
+    }
+
+    if (JimValidName(interp, "new procedure", argv[2])) {
+        return JIM_ERR;
+    }
+
+    return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
+}
+
+#define JIM_DICTMATCH_VALUES 0x0001
+
+typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);
+
+static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
+{
+    Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
+    if (type & JIM_DICTMATCH_VALUES) {
+        Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->u.val);
+    }
+}
+
+static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
+    JimDictMatchCallbackType *callback, int type)
+{
+    Jim_HashEntry *he;
+    Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
+
+    
+    Jim_HashTableIterator htiter;
+    JimInitHashTableIterator(ht, &htiter);
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
+            callback(interp, listObjPtr, he, type);
+        }
+    }
+
+    return listObjPtr;
+}
+
+
+int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
+{
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0));
+    return JIM_OK;
+}
+
+int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
+{
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES));
+    return JIM_OK;
+}
+
+int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return -1;
+    }
+    return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
+}
+
+
+static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+    int option;
+    static const char * const options[] = {
+        "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
+    };
+    enum
+    {
+        OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
+    };
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?");
+        return JIM_ERR;
+    }
+
+    if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    switch (option) {
+        case OPT_GET:
+            if (argc < 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
+                return JIM_ERR;
+            }
+            if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
+                    JIM_ERRMSG) != JIM_OK) {
+                return JIM_ERR;
+            }
+            Jim_SetResult(interp, objPtr);
+            return JIM_OK;
+
+        case OPT_SET:
+            if (argc < 5) {
+                Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value");
+                return JIM_ERR;
+            }
+            return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
+
+        case OPT_EXIST:
+            if (argc < 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
+                return JIM_ERR;
+            }
+            Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
+                    &objPtr, JIM_ERRMSG) == JIM_OK);
+            return JIM_OK;
+
+        case OPT_UNSET:
+            if (argc < 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
+                return JIM_ERR;
+            }
+            return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
+
+        case OPT_KEYS:
+            if (argc != 3 && argc != 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
+                return JIM_ERR;
+            }
+            return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
+
+        case OPT_SIZE: {
+            int size;
+
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "dictVar");
+                return JIM_ERR;
+            }
+
+            size = Jim_DictSize(interp, argv[2]);
+            if (size < 0) {
+                return JIM_ERR;
+            }
+            Jim_SetResultInt(interp, size);
+            return JIM_OK;
+        }
+
+        case OPT_MERGE:
+            if (argc == 2) {
+                return JIM_OK;
+            }
+            else if (SetDictFromAny(interp, argv[2]) != JIM_OK) {
+                return JIM_ERR;
+            }
+            else {
+                return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
+            }
+
+        case OPT_WITH:
+            if (argc < 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
+                return JIM_ERR;
+            }
+            else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
+                return JIM_ERR;
+            }
+            else {
+                return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
+            }
+
+        case OPT_CREATE:
+            if (argc % 2) {
+                Jim_WrongNumArgs(interp, 2, argv, "?key value ...?");
+                return JIM_ERR;
+            }
+            objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2);
+            Jim_SetResult(interp, objPtr);
+            return JIM_OK;
+    }
+    return JIM_ERR;
+}
+
+
+static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    static const char * const options[] = {
+        "-nobackslashes", "-nocommands", "-novariables", NULL
+    };
+    enum
+    { OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES };
+    int i;
+    int flags = JIM_SUBST_FLAG;
+    Jim_Obj *objPtr;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "?options? string");
+        return JIM_ERR;
+    }
+    for (i = 1; i < (argc - 1); i++) {
+        int option;
+
+        if (Jim_GetEnum(interp, argv[i], options, &option, NULL,
+                JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+            return JIM_ERR;
+        }
+        switch (option) {
+            case OPT_NOBACKSLASHES:
+                flags |= JIM_SUBST_NOESC;
+                break;
+            case OPT_NOCOMMANDS:
+                flags |= JIM_SUBST_NOCMD;
+                break;
+            case OPT_NOVARIABLES:
+                flags |= JIM_SUBST_NOVAR;
+                break;
+        }
+    }
+    if (Jim_SubstObj(interp, argv[argc - 1], &objPtr, flags) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, objPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int cmd;
+    Jim_Obj *objPtr;
+    int mode = 0;
+
+    static const char * const commands[] = {
+        "body", "statics", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals",
+        "vars", "version", "patchlevel", "complete", "args", "hostname",
+        "script", "source", "stacktrace", "nameofexecutable", "returncodes",
+        "references", "alias", NULL
+    };
+    enum
+    { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
+        INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
+        INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
+        INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS
+    };
+
+#ifdef jim_ext_namespace
+    int nons = 0;
+
+    if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
+        
+        argc--;
+        argv++;
+        nons = 1;
+    }
+#endif
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
+        return JIM_ERR;
+    }
+    if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV)
+        != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    
+    switch (cmd) {
+        case INFO_EXISTS:
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "varName");
+                return JIM_ERR;
+            }
+            Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL);
+            break;
+
+        case INFO_ALIAS:{
+            Jim_Cmd *cmdPtr;
+
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "command");
+                return JIM_ERR;
+            }
+            if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) {
+                return JIM_ERR;
+            }
+            if (cmdPtr->isproc || cmdPtr->u.native.cmdProc != JimAliasCmd) {
+                Jim_SetResultFormatted(interp, "command \"%#s\" is not an alias", argv[2]);
+                return JIM_ERR;
+            }
+            Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
+            return JIM_OK;
+        }
+
+        case INFO_CHANNELS:
+            mode++;             
+#ifndef jim_ext_aio
+            Jim_SetResultString(interp, "aio not enabled", -1);
+            return JIM_ERR;
+#endif
+        case INFO_PROCS:
+            mode++;             
+        case INFO_COMMANDS:
+            
+            if (argc != 2 && argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
+                return JIM_ERR;
+            }
+#ifdef jim_ext_namespace
+            if (!nons) {
+                if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+                    return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
+                }
+            }
+#endif
+            Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
+            break;
+
+        case INFO_VARS:
+            mode++;             
+        case INFO_LOCALS:
+            mode++;             
+        case INFO_GLOBALS:
+            
+            if (argc != 2 && argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
+                return JIM_ERR;
+            }
+#ifdef jim_ext_namespace
+            if (!nons) {
+                if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+                    return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
+                }
+            }
+#endif
+            Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode));
+            break;
+
+        case INFO_SCRIPT:
+            if (argc != 2) {
+                Jim_WrongNumArgs(interp, 2, argv, "");
+                return JIM_ERR;
+            }
+            Jim_SetResult(interp, Jim_GetScript(interp, interp->currentScriptObj)->fileNameObj);
+            break;
+
+        case INFO_SOURCE:{
+                int line;
+                Jim_Obj *resObjPtr;
+                Jim_Obj *fileNameObj;
+
+                if (argc != 3) {
+                    Jim_WrongNumArgs(interp, 2, argv, "source");
+                    return JIM_ERR;
+                }
+                if (argv[2]->typePtr == &sourceObjType) {
+                    fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj;
+                    line = argv[2]->internalRep.sourceValue.lineNumber;
+                }
+                else if (argv[2]->typePtr == &scriptObjType) {
+                    ScriptObj *script = Jim_GetScript(interp, argv[2]);
+                    fileNameObj = script->fileNameObj;
+                    line = script->firstline;
+                }
+                else {
+                    fileNameObj = interp->emptyObj;
+                    line = 1;
+                }
+                resObjPtr = Jim_NewListObj(interp, NULL, 0);
+                Jim_ListAppendElement(interp, resObjPtr, fileNameObj);
+                Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line));
+                Jim_SetResult(interp, resObjPtr);
+                break;
+            }
+
+        case INFO_STACKTRACE:
+            Jim_SetResult(interp, interp->stackTrace);
+            break;
+
+        case INFO_LEVEL:
+        case INFO_FRAME:
+            switch (argc) {
+                case 2:
+                    Jim_SetResultInt(interp, interp->framePtr->level);
+                    break;
+
+                case 3:
+                    if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) {
+                        return JIM_ERR;
+                    }
+                    Jim_SetResult(interp, objPtr);
+                    break;
+
+                default:
+                    Jim_WrongNumArgs(interp, 2, argv, "?levelNum?");
+                    return JIM_ERR;
+            }
+            break;
+
+        case INFO_BODY:
+        case INFO_STATICS:
+        case INFO_ARGS:{
+                Jim_Cmd *cmdPtr;
+
+                if (argc != 3) {
+                    Jim_WrongNumArgs(interp, 2, argv, "procname");
+                    return JIM_ERR;
+                }
+                if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) {
+                    return JIM_ERR;
+                }
+                if (!cmdPtr->isproc) {
+                    Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]);
+                    return JIM_ERR;
+                }
+                switch (cmd) {
+                    case INFO_BODY:
+                        Jim_SetResult(interp, cmdPtr->u.proc.bodyObjPtr);
+                        break;
+                    case INFO_ARGS:
+                        Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
+                        break;
+                    case INFO_STATICS:
+                        if (cmdPtr->u.proc.staticVars) {
+                            int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES;
+                            Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
+                                NULL, JimVariablesMatch, mode));
+                        }
+                        break;
+                }
+                break;
+            }
+
+        case INFO_VERSION:
+        case INFO_PATCHLEVEL:{
+                char buf[(JIM_INTEGER_SPACE * 2) + 1];
+
+                sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100);
+                Jim_SetResultString(interp, buf, -1);
+                break;
+            }
+
+        case INFO_COMPLETE:
+            if (argc != 3 && argc != 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "script ?missing?");
+                return JIM_ERR;
+            }
+            else {
+                int len;
+                const char *s = Jim_GetString(argv[2], &len);
+                char missing;
+
+                Jim_SetResultBool(interp, Jim_ScriptIsComplete(s, len, &missing));
+                if (missing != ' ' && argc == 4) {
+                    Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1));
+                }
+            }
+            break;
+
+        case INFO_HOSTNAME:
+            
+            return Jim_Eval(interp, "os.gethostname");
+
+        case INFO_NAMEOFEXECUTABLE:
+            
+            return Jim_Eval(interp, "{info nameofexecutable}");
+
+        case INFO_RETURNCODES:
+            if (argc == 2) {
+                int i;
+                Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
+
+                for (i = 0; jimReturnCodes[i]; i++) {
+                    Jim_ListAppendElement(interp, listObjPtr, Jim_NewIntObj(interp, i));
+                    Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp,
+                            jimReturnCodes[i], -1));
+                }
+
+                Jim_SetResult(interp, listObjPtr);
+            }
+            else if (argc == 3) {
+                long code;
+                const char *name;
+
+                if (Jim_GetLong(interp, argv[2], &code) != JIM_OK) {
+                    return JIM_ERR;
+                }
+                name = Jim_ReturnCode(code);
+                if (*name == '?') {
+                    Jim_SetResultInt(interp, code);
+                }
+                else {
+                    Jim_SetResultString(interp, name, -1);
+                }
+            }
+            else {
+                Jim_WrongNumArgs(interp, 2, argv, "?code?");
+                return JIM_ERR;
+            }
+            break;
+        case INFO_REFERENCES:
+#ifdef JIM_REFERENCES
+            return JimInfoReferences(interp, argc, argv);
+#else
+            Jim_SetResultString(interp, "not supported", -1);
+            return JIM_ERR;
+#endif
+    }
+    return JIM_OK;
+}
+
+
+static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+    int result = 0;
+
+    static const char * const options[] = {
+        "-command", "-proc", "-alias", "-var", NULL
+    };
+    enum
+    {
+        OPT_COMMAND, OPT_PROC, OPT_ALIAS, OPT_VAR
+    };
+    int option;
+
+    if (argc == 2) {
+        option = OPT_VAR;
+        objPtr = argv[1];
+    }
+    else if (argc == 3) {
+        if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+            return JIM_ERR;
+        }
+        objPtr = argv[2];
+    }
+    else {
+        Jim_WrongNumArgs(interp, 1, argv, "?option? name");
+        return JIM_ERR;
+    }
+
+    if (option == OPT_VAR) {
+        result = Jim_GetVariable(interp, objPtr, 0) != NULL;
+    }
+    else {
+        
+        Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
+
+        if (cmd) {
+            switch (option) {
+            case OPT_COMMAND:
+                result = 1;
+                break;
+
+            case OPT_ALIAS:
+                result = cmd->isproc == 0 && cmd->u.native.cmdProc == JimAliasCmd;
+                break;
+
+            case OPT_PROC:
+                result = cmd->isproc;
+                break;
+            }
+        }
+    }
+    Jim_SetResultBool(interp, result);
+    return JIM_OK;
+}
+
+
+static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *str, *splitChars, *noMatchStart;
+    int splitLen, strLen;
+    Jim_Obj *resObjPtr;
+    int c;
+    int len;
+
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "string ?splitChars?");
+        return JIM_ERR;
+    }
+
+    str = Jim_GetString(argv[1], &len);
+    if (len == 0) {
+        return JIM_OK;
+    }
+    strLen = Jim_Utf8Length(interp, argv[1]);
+
+    
+    if (argc == 2) {
+        splitChars = " \n\t\r";
+        splitLen = 4;
+    }
+    else {
+        splitChars = Jim_String(argv[2]);
+        splitLen = Jim_Utf8Length(interp, argv[2]);
+    }
+
+    noMatchStart = str;
+    resObjPtr = Jim_NewListObj(interp, NULL, 0);
+
+    
+    if (splitLen) {
+        Jim_Obj *objPtr;
+        while (strLen--) {
+            const char *sc = splitChars;
+            int scLen = splitLen;
+            int sl = utf8_tounicode(str, &c);
+            while (scLen--) {
+                int pc;
+                sc += utf8_tounicode(sc, &pc);
+                if (c == pc) {
+                    objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart));
+                    Jim_ListAppendElement(interp, resObjPtr, objPtr);
+                    noMatchStart = str + sl;
+                    break;
+                }
+            }
+            str += sl;
+        }
+        objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart));
+        Jim_ListAppendElement(interp, resObjPtr, objPtr);
+    }
+    else {
+        Jim_Obj **commonObj = NULL;
+#define NUM_COMMON (128 - 9)
+        while (strLen--) {
+            int n = utf8_tounicode(str, &c);
+#ifdef JIM_OPTIMIZATION
+            if (c >= 9 && c < 128) {
+                
+                c -= 9;
+                if (!commonObj) {
+                    commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON);
+                    memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON);
+                }
+                if (!commonObj[c]) {
+                    commonObj[c] = Jim_NewStringObj(interp, str, 1);
+                }
+                Jim_ListAppendElement(interp, resObjPtr, commonObj[c]);
+                str++;
+                continue;
+            }
+#endif
+            Jim_ListAppendElement(interp, resObjPtr, Jim_NewStringObjUtf8(interp, str, 1));
+            str += n;
+        }
+        Jim_Free(commonObj);
+    }
+
+    Jim_SetResult(interp, resObjPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *joinStr;
+    int joinStrLen;
+
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
+        return JIM_ERR;
+    }
+    
+    if (argc == 2) {
+        joinStr = " ";
+        joinStrLen = 1;
+    }
+    else {
+        joinStr = Jim_GetString(argv[2], &joinStrLen);
+    }
+    Jim_SetResult(interp, Jim_ListJoin(interp, argv[1], joinStr, joinStrLen));
+    return JIM_OK;
+}
+
+
+static int Jim_FormatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "formatString ?arg arg ...?");
+        return JIM_ERR;
+    }
+    objPtr = Jim_FormatString(interp, argv[1], argc - 2, argv + 2);
+    if (objPtr == NULL)
+        return JIM_ERR;
+    Jim_SetResult(interp, objPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_ScanCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *listPtr, **outVec;
+    int outc, i;
+
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "string format ?varName varName ...?");
+        return JIM_ERR;
+    }
+    if (argv[2]->typePtr != &scanFmtStringObjType)
+        SetScanFmtFromAny(interp, argv[2]);
+    if (FormatGetError(argv[2]) != 0) {
+        Jim_SetResultString(interp, FormatGetError(argv[2]), -1);
+        return JIM_ERR;
+    }
+    if (argc > 3) {
+        int maxPos = FormatGetMaxPos(argv[2]);
+        int count = FormatGetCnvCount(argv[2]);
+
+        if (maxPos > argc - 3) {
+            Jim_SetResultString(interp, "\"%n$\" argument index out of range", -1);
+            return JIM_ERR;
+        }
+        else if (count > argc - 3) {
+            Jim_SetResultString(interp, "different numbers of variable names and "
+                "field specifiers", -1);
+            return JIM_ERR;
+        }
+        else if (count < argc - 3) {
+            Jim_SetResultString(interp, "variable is not assigned by any "
+                "conversion specifiers", -1);
+            return JIM_ERR;
+        }
+    }
+    listPtr = Jim_ScanString(interp, argv[1], argv[2], JIM_ERRMSG);
+    if (listPtr == 0)
+        return JIM_ERR;
+    if (argc > 3) {
+        int rc = JIM_OK;
+        int count = 0;
+
+        if (listPtr != 0 && listPtr != (Jim_Obj *)EOF) {
+            int len = Jim_ListLength(interp, listPtr);
+
+            if (len != 0) {
+                JimListGetElements(interp, listPtr, &outc, &outVec);
+                for (i = 0; i < outc; ++i) {
+                    if (Jim_Length(outVec[i]) > 0) {
+                        ++count;
+                        if (Jim_SetVariable(interp, argv[3 + i], outVec[i]) != JIM_OK) {
+                            rc = JIM_ERR;
+                        }
+                    }
+                }
+            }
+            Jim_FreeNewObj(interp, listPtr);
+        }
+        else {
+            count = -1;
+        }
+        if (rc == JIM_OK) {
+            Jim_SetResultInt(interp, count);
+        }
+        return rc;
+    }
+    else {
+        if (listPtr == (Jim_Obj *)EOF) {
+            Jim_SetResult(interp, Jim_NewListObj(interp, 0, 0));
+            return JIM_OK;
+        }
+        Jim_SetResult(interp, listPtr);
+    }
+    return JIM_OK;
+}
+
+
+static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc != 2 && argc != 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "message ?stacktrace?");
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, argv[1]);
+    if (argc == 3) {
+        JimSetStackTrace(interp, argv[2]);
+        return JIM_ERR;
+    }
+    interp->addStackTrace++;
+    return JIM_ERR;
+}
+
+
+static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+
+    if (argc != 4) {
+        Jim_WrongNumArgs(interp, 1, argv, "list first last");
+        return JIM_ERR;
+    }
+    if ((objPtr = Jim_ListRange(interp, argv[1], argv[2], argv[3])) == NULL)
+        return JIM_ERR;
+    Jim_SetResult(interp, objPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+    long count;
+
+    if (argc < 2 || Jim_GetLong(interp, argv[1], &count) != JIM_OK || count < 0) {
+        Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?");
+        return JIM_ERR;
+    }
+
+    if (count == 0 || argc == 2) {
+        return JIM_OK;
+    }
+
+    argc -= 2;
+    argv += 2;
+
+    objPtr = Jim_NewListObj(interp, argv, argc);
+    while (--count) {
+        ListInsertElements(objPtr, -1, argc, argv);
+    }
+
+    Jim_SetResult(interp, objPtr);
+    return JIM_OK;
+}
+
+char **Jim_GetEnviron(void)
+{
+#if defined(HAVE__NSGETENVIRON)
+    return *_NSGetEnviron();
+#else
+    #if !defined(NO_ENVIRON_EXTERN)
+    extern char **environ;
+    #endif
+
+    return environ;
+#endif
+}
+
+void Jim_SetEnviron(char **env)
+{
+#if defined(HAVE__NSGETENVIRON)
+    *_NSGetEnviron() = env;
+#else
+    #if !defined(NO_ENVIRON_EXTERN)
+    extern char **environ;
+    #endif
+
+    environ = env;
+#endif
+}
+
+
+static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const char *key;
+    const char *val;
+
+    if (argc == 1) {
+        char **e = Jim_GetEnviron();
+
+        int i;
+        Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
+
+        for (i = 0; e[i]; i++) {
+            const char *equals = strchr(e[i], '=');
+
+            if (equals) {
+                Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, e[i],
+                        equals - e[i]));
+                Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, equals + 1, -1));
+            }
+        }
+
+        Jim_SetResult(interp, listObjPtr);
+        return JIM_OK;
+    }
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "varName ?default?");
+        return JIM_ERR;
+    }
+    key = Jim_String(argv[1]);
+    val = getenv(key);
+    if (val == NULL) {
+        if (argc < 3) {
+            Jim_SetResultFormatted(interp, "environment variable \"%#s\" does not exist", argv[1]);
+            return JIM_ERR;
+        }
+        val = Jim_String(argv[2]);
+    }
+    Jim_SetResult(interp, Jim_NewStringObj(interp, val, -1));
+    return JIM_OK;
+}
+
+
+static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int retval;
+
+    if (argc != 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "fileName");
+        return JIM_ERR;
+    }
+    retval = Jim_EvalFile(interp, Jim_String(argv[1]));
+    if (retval == JIM_RETURN)
+        return JIM_OK;
+    return retval;
+}
+
+
+static int Jim_LreverseCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *revObjPtr, **ele;
+    int len;
+
+    if (argc != 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "list");
+        return JIM_ERR;
+    }
+    JimListGetElements(interp, argv[1], &len, &ele);
+    len--;
+    revObjPtr = Jim_NewListObj(interp, NULL, 0);
+    while (len >= 0)
+        ListAppendElement(revObjPtr, ele[len--]);
+    Jim_SetResult(interp, revObjPtr);
+    return JIM_OK;
+}
+
+static int JimRangeLen(jim_wide start, jim_wide end, jim_wide step)
+{
+    jim_wide len;
+
+    if (step == 0)
+        return -1;
+    if (start == end)
+        return 0;
+    else if (step > 0 && start > end)
+        return -1;
+    else if (step < 0 && end > start)
+        return -1;
+    len = end - start;
+    if (len < 0)
+        len = -len;             
+    if (step < 0)
+        step = -step;           
+    len = 1 + ((len - 1) / step);
+    if (len > INT_MAX)
+        len = INT_MAX;
+    return (int)((len < 0) ? -1 : len);
+}
+
+
+static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    jim_wide start = 0, end, step = 1;
+    int len, i;
+    Jim_Obj *objPtr;
+
+    if (argc < 2 || argc > 4) {
+        Jim_WrongNumArgs(interp, 1, argv, "?start? end ?step?");
+        return JIM_ERR;
+    }
+    if (argc == 2) {
+        if (Jim_GetWide(interp, argv[1], &end) != JIM_OK)
+            return JIM_ERR;
+    }
+    else {
+        if (Jim_GetWide(interp, argv[1], &start) != JIM_OK ||
+            Jim_GetWide(interp, argv[2], &end) != JIM_OK)
+            return JIM_ERR;
+        if (argc == 4 && Jim_GetWide(interp, argv[3], &step) != JIM_OK)
+            return JIM_ERR;
+    }
+    if ((len = JimRangeLen(start, end, step)) == -1) {
+        Jim_SetResultString(interp, "Invalid (infinite?) range specified", -1);
+        return JIM_ERR;
+    }
+    objPtr = Jim_NewListObj(interp, NULL, 0);
+    for (i = 0; i < len; i++)
+        ListAppendElement(objPtr, Jim_NewIntObj(interp, start + i * step));
+    Jim_SetResult(interp, objPtr);
+    return JIM_OK;
+}
+
+
+static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    jim_wide min = 0, max = 0, len, maxMul;
+
+    if (argc < 1 || argc > 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "?min? max");
+        return JIM_ERR;
+    }
+    if (argc == 1) {
+        max = JIM_WIDE_MAX;
+    } else if (argc == 2) {
+        if (Jim_GetWide(interp, argv[1], &max) != JIM_OK)
+            return JIM_ERR;
+    } else if (argc == 3) {
+        if (Jim_GetWide(interp, argv[1], &min) != JIM_OK ||
+            Jim_GetWide(interp, argv[2], &max) != JIM_OK)
+            return JIM_ERR;
+    }
+    len = max-min;
+    if (len < 0) {
+        Jim_SetResultString(interp, "Invalid arguments (max < min)", -1);
+        return JIM_ERR;
+    }
+    maxMul = JIM_WIDE_MAX - (len ? (JIM_WIDE_MAX%len) : 0);
+    while (1) {
+        jim_wide r;
+
+        JimRandomBytes(interp, &r, sizeof(jim_wide));
+        if (r < 0 || r >= maxMul) continue;
+        r = (len == 0) ? 0 : r%len;
+        Jim_SetResultInt(interp, min+r);
+        return JIM_OK;
+    }
+}
+
+static const struct {
+    const char *name;
+    Jim_CmdProc cmdProc;
+} Jim_CoreCommandsTable[] = {
+    {"alias", Jim_AliasCoreCommand},
+    {"set", Jim_SetCoreCommand},
+    {"unset", Jim_UnsetCoreCommand},
+    {"puts", Jim_PutsCoreCommand},
+    {"+", Jim_AddCoreCommand},
+    {"*", Jim_MulCoreCommand},
+    {"-", Jim_SubCoreCommand},
+    {"/", Jim_DivCoreCommand},
+    {"incr", Jim_IncrCoreCommand},
+    {"while", Jim_WhileCoreCommand},
+    {"loop", Jim_LoopCoreCommand},
+    {"for", Jim_ForCoreCommand},
+    {"foreach", Jim_ForeachCoreCommand},
+    {"lmap", Jim_LmapCoreCommand},
+    {"lassign", Jim_LassignCoreCommand},
+    {"if", Jim_IfCoreCommand},
+    {"switch", Jim_SwitchCoreCommand},
+    {"list", Jim_ListCoreCommand},
+    {"lindex", Jim_LindexCoreCommand},
+    {"lset", Jim_LsetCoreCommand},
+    {"lsearch", Jim_LsearchCoreCommand},
+    {"llength", Jim_LlengthCoreCommand},
+    {"lappend", Jim_LappendCoreCommand},
+    {"linsert", Jim_LinsertCoreCommand},
+    {"lreplace", Jim_LreplaceCoreCommand},
+    {"lsort", Jim_LsortCoreCommand},
+    {"append", Jim_AppendCoreCommand},
+    {"debug", Jim_DebugCoreCommand},
+    {"eval", Jim_EvalCoreCommand},
+    {"uplevel", Jim_UplevelCoreCommand},
+    {"expr", Jim_ExprCoreCommand},
+    {"break", Jim_BreakCoreCommand},
+    {"continue", Jim_ContinueCoreCommand},
+    {"proc", Jim_ProcCoreCommand},
+    {"concat", Jim_ConcatCoreCommand},
+    {"return", Jim_ReturnCoreCommand},
+    {"upvar", Jim_UpvarCoreCommand},
+    {"global", Jim_GlobalCoreCommand},
+    {"string", Jim_StringCoreCommand},
+    {"time", Jim_TimeCoreCommand},
+    {"exit", Jim_ExitCoreCommand},
+    {"catch", Jim_CatchCoreCommand},
+#ifdef JIM_REFERENCES
+    {"ref", Jim_RefCoreCommand},
+    {"getref", Jim_GetrefCoreCommand},
+    {"setref", Jim_SetrefCoreCommand},
+    {"finalize", Jim_FinalizeCoreCommand},
+    {"collect", Jim_CollectCoreCommand},
+#endif
+    {"rename", Jim_RenameCoreCommand},
+    {"dict", Jim_DictCoreCommand},
+    {"subst", Jim_SubstCoreCommand},
+    {"info", Jim_InfoCoreCommand},
+    {"exists", Jim_ExistsCoreCommand},
+    {"split", Jim_SplitCoreCommand},
+    {"join", Jim_JoinCoreCommand},
+    {"format", Jim_FormatCoreCommand},
+    {"scan", Jim_ScanCoreCommand},
+    {"error", Jim_ErrorCoreCommand},
+    {"lrange", Jim_LrangeCoreCommand},
+    {"lrepeat", Jim_LrepeatCoreCommand},
+    {"env", Jim_EnvCoreCommand},
+    {"source", Jim_SourceCoreCommand},
+    {"lreverse", Jim_LreverseCoreCommand},
+    {"range", Jim_RangeCoreCommand},
+    {"rand", Jim_RandCoreCommand},
+    {"tailcall", Jim_TailcallCoreCommand},
+    {"local", Jim_LocalCoreCommand},
+    {"upcall", Jim_UpcallCoreCommand},
+    {"apply", Jim_ApplyCoreCommand},
+    {NULL, NULL},
+};
+
+void Jim_RegisterCoreCommands(Jim_Interp *interp)
+{
+    int i = 0;
+
+    while (Jim_CoreCommandsTable[i].name != NULL) {
+        Jim_CreateCommand(interp,
+            Jim_CoreCommandsTable[i].name, Jim_CoreCommandsTable[i].cmdProc, NULL, NULL);
+        i++;
+    }
+}
+
+void Jim_MakeErrorMessage(Jim_Interp *interp)
+{
+    Jim_Obj *argv[2];
+
+    argv[0] = Jim_NewStringObj(interp, "errorInfo", -1);
+    argv[1] = interp->result;
+
+    Jim_EvalObjVector(interp, 2, argv);
+}
+
+static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
+    const char *prefix, const char *const *tablePtr, const char *name)
+{
+    int count;
+    char **tablePtrSorted;
+    int i;
+
+    for (count = 0; tablePtr[count]; count++) {
+    }
+
+    if (name == NULL) {
+        name = "option";
+    }
+
+    Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg);
+    tablePtrSorted = Jim_Alloc(sizeof(char *) * count);
+    memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count);
+    qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers);
+    for (i = 0; i < count; i++) {
+        if (i + 1 == count && count > 1) {
+            Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1);
+        }
+        Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL);
+        if (i + 1 != count) {
+            Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1);
+        }
+    }
+    Jim_Free(tablePtrSorted);
+}
+
+int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr,
+    const char *const *tablePtr, int *indexPtr, const char *name, int flags)
+{
+    const char *bad = "bad ";
+    const char *const *entryPtr = NULL;
+    int i;
+    int match = -1;
+    int arglen;
+    const char *arg = Jim_GetString(objPtr, &arglen);
+
+    *indexPtr = -1;
+
+    for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) {
+        if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) {
+            
+            *indexPtr = i;
+            return JIM_OK;
+        }
+        if (flags & JIM_ENUM_ABBREV) {
+            if (strncmp(arg, *entryPtr, arglen) == 0) {
+                if (*arg == '-' && arglen == 1) {
+                    break;
+                }
+                if (match >= 0) {
+                    bad = "ambiguous ";
+                    goto ambiguous;
+                }
+                match = i;
+            }
+        }
+    }
+
+    
+    if (match >= 0) {
+        *indexPtr = match;
+        return JIM_OK;
+    }
+
+  ambiguous:
+    if (flags & JIM_ERRMSG) {
+        JimSetFailedEnumResult(interp, arg, bad, "", tablePtr, name);
+    }
+    return JIM_ERR;
+}
+
+int Jim_FindByName(const char *name, const char * const array[], size_t len)
+{
+    int i;
+
+    for (i = 0; i < (int)len; i++) {
+        if (array[i] && strcmp(array[i], name) == 0) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+int Jim_IsDict(Jim_Obj *objPtr)
+{
+    return objPtr->typePtr == &dictObjType;
+}
+
+int Jim_IsList(Jim_Obj *objPtr)
+{
+    return objPtr->typePtr == &listObjType;
+}
+
+void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
+{
+    
+    int len = strlen(format);
+    int extra = 0;
+    int n = 0;
+    const char *params[5];
+    char *buf;
+    va_list args;
+    int i;
+
+    va_start(args, format);
+
+    for (i = 0; i < len && n < 5; i++) {
+        int l;
+
+        if (strncmp(format + i, "%s", 2) == 0) {
+            params[n] = va_arg(args, char *);
+
+            l = strlen(params[n]);
+        }
+        else if (strncmp(format + i, "%#s", 3) == 0) {
+            Jim_Obj *objPtr = va_arg(args, Jim_Obj *);
+
+            params[n] = Jim_GetString(objPtr, &l);
+        }
+        else {
+            if (format[i] == '%') {
+                i++;
+            }
+            continue;
+        }
+        n++;
+        extra += l;
+    }
+
+    len += extra;
+    buf = Jim_Alloc(len + 1);
+    len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
+
+    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
+}
+
+
+#ifndef jim_ext_package
+int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags)
+{
+    return JIM_OK;
+}
+#endif
+#ifndef jim_ext_aio
+FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj)
+{
+    Jim_SetResultString(interp, "aio not enabled", -1);
+    return NULL;
+}
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    
+    return JIM_OK;
+}
+
+static const jim_subcmd_type dummy_subcmd = {
+    "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
+};
+
+static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep)
+{
+    const char *s = "";
+
+    for (; ct->cmd; ct++) {
+        if (!(ct->flags & JIM_MODFLAG_HIDDEN)) {
+            Jim_AppendStrings(interp, Jim_GetResult(interp), s, ct->cmd, NULL);
+            s = sep;
+        }
+    }
+}
+
+static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type,
+    Jim_Obj *cmd, Jim_Obj *subcmd)
+{
+    Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+    Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type,
+        " command \"", Jim_String(subcmd), "\": should be ", NULL);
+    add_commands(interp, command_table, ", ");
+}
+
+static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
+    Jim_Obj *const *argv)
+{
+    Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+    Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]),
+        " command ... \", where command is one of: ", NULL);
+    add_commands(interp, command_table, ", ");
+}
+
+static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd)
+{
+    if (cmd) {
+        Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), " ", NULL);
+    }
+    Jim_AppendStrings(interp, Jim_GetResult(interp), ct->cmd, NULL);
+    if (ct->args && *ct->args) {
+        Jim_AppendStrings(interp, Jim_GetResult(interp), " ", ct->args, NULL);
+    }
+}
+
+static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd)
+{
+    Jim_SetResultString(interp, "wrong # args: should be \"", -1);
+    add_cmd_usage(interp, command_table, subcmd);
+    Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
+}
+
+const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table,
+    int argc, Jim_Obj *const *argv)
+{
+    const jim_subcmd_type *ct;
+    const jim_subcmd_type *partial = 0;
+    int cmdlen;
+    Jim_Obj *cmd;
+    const char *cmdstr;
+    const char *cmdname;
+    int help = 0;
+
+    cmdname = Jim_String(argv[0]);
+
+    if (argc < 2) {
+        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+        Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname,
+            " command ...\"\n", NULL);
+        Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL);
+        return 0;
+    }
+
+    cmd = argv[1];
+
+    
+    if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
+        if (argc == 2) {
+            
+            show_cmd_usage(interp, command_table, argc, argv);
+            return &dummy_subcmd;
+        }
+        help = 1;
+
+        
+        cmd = argv[2];
+    }
+
+    
+    if (Jim_CompareStringImmediate(interp, cmd, "-commands")) {
+        
+        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+        add_commands(interp, command_table, " ");
+        return &dummy_subcmd;
+    }
+
+    cmdstr = Jim_GetString(cmd, &cmdlen);
+
+    for (ct = command_table; ct->cmd; ct++) {
+        if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) {
+            
+            break;
+        }
+        if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) {
+            if (partial) {
+                
+                if (help) {
+                    
+                    show_cmd_usage(interp, command_table, argc, argv);
+                    return &dummy_subcmd;
+                }
+                bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]);
+                return 0;
+            }
+            partial = ct;
+        }
+        continue;
+    }
+
+    
+    if (partial && !ct->cmd) {
+        ct = partial;
+    }
+
+    if (!ct->cmd) {
+        
+        if (help) {
+            
+            show_cmd_usage(interp, command_table, argc, argv);
+            return &dummy_subcmd;
+        }
+        bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]);
+        return 0;
+    }
+
+    if (help) {
+        Jim_SetResultString(interp, "Usage: ", -1);
+        
+        add_cmd_usage(interp, ct, argv[0]);
+        return &dummy_subcmd;
+    }
+
+    
+    if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
+        Jim_SetResultString(interp, "wrong # args: should be \"", -1);
+        
+        add_cmd_usage(interp, ct, argv[0]);
+        Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
+
+        return 0;
+    }
+
+    
+    return ct;
+}
+
+int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv)
+{
+    int ret = JIM_ERR;
+
+    if (ct) {
+        if (ct->flags & JIM_MODFLAG_FULLARGV) {
+            ret = ct->function(interp, argc, argv);
+        }
+        else {
+            ret = ct->function(interp, argc - 2, argv + 2);
+        }
+        if (ret < 0) {
+            set_wrong_args(interp, ct, argv[0]);
+            ret = JIM_ERR;
+        }
+    }
+    return ret;
+}
+
+int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const jim_subcmd_type *ct =
+        Jim_ParseSubCmd(interp, (const jim_subcmd_type *)Jim_CmdPrivData(interp), argc, argv);
+
+    return Jim_CallSubCmd(interp, ct, argc, argv);
+}
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+
+int utf8_fromunicode(char *p, unsigned uc)
+{
+    if (uc <= 0x7f) {
+        *p = uc;
+        return 1;
+    }
+    else if (uc <= 0x7ff) {
+        *p++ = 0xc0 | ((uc & 0x7c0) >> 6);
+        *p = 0x80 | (uc & 0x3f);
+        return 2;
+    }
+    else if (uc <= 0xffff) {
+        *p++ = 0xe0 | ((uc & 0xf000) >> 12);
+        *p++ = 0x80 | ((uc & 0xfc0) >> 6);
+        *p = 0x80 | (uc & 0x3f);
+        return 3;
+    }
+    
+    else {
+        *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
+        *p++ = 0x80 | ((uc & 0x3f000) >> 12);
+        *p++ = 0x80 | ((uc & 0xfc0) >> 6);
+        *p = 0x80 | (uc & 0x3f);
+        return 4;
+    }
+}
+
+#include <ctype.h>
+#include <string.h>
+
+
+#define JIM_UTF_MAX 3
+#define JIM_INTEGER_SPACE 24
+#define MAX_FLOAT_WIDTH 320
+
+Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv)
+{
+    const char *span, *format, *formatEnd, *msg;
+    int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
+    static const char * const mixedXPG =
+           "cannot mix \"%\" and \"%n$\" conversion specifiers";
+    static const char * const badIndex[2] = {
+       "not enough arguments for all format specifiers",
+       "\"%n$\" argument index out of range"
+    };
+    int formatLen;
+    Jim_Obj *resultPtr;
+
+    char *num_buffer = NULL;
+    int num_buffer_size = 0;
+
+    span = format = Jim_GetString(fmtObjPtr, &formatLen);
+    formatEnd = format + formatLen;
+    resultPtr = Jim_NewEmptyStringObj(interp);
+
+    while (format != formatEnd) {
+       char *end;
+       int gotMinus, sawFlag;
+       int gotPrecision, useShort;
+       long width, precision;
+       int newXpg;
+       int ch;
+       int step;
+       int doubleType;
+       char pad = ' ';
+       char spec[2*JIM_INTEGER_SPACE + 12];
+       char *p;
+
+       int formatted_chars;
+       int formatted_bytes;
+       const char *formatted_buf;
+
+       step = utf8_tounicode(format, &ch);
+       format += step;
+       if (ch != '%') {
+           numBytes += step;
+           continue;
+       }
+       if (numBytes) {
+           Jim_AppendString(interp, resultPtr, span, numBytes);
+           numBytes = 0;
+       }
+
+
+       step = utf8_tounicode(format, &ch);
+       if (ch == '%') {
+           span = format;
+           numBytes = step;
+           format += step;
+           continue;
+       }
+
+
+       newXpg = 0;
+       if (isdigit(ch)) {
+           int position = strtoul(format, &end, 10);
+           if (*end == '$') {
+               newXpg = 1;
+               objIndex = position - 1;
+               format = end + 1;
+               step = utf8_tounicode(format, &ch);
+           }
+       }
+       if (newXpg) {
+           if (gotSequential) {
+               msg = mixedXPG;
+               goto errorMsg;
+           }
+           gotXpg = 1;
+       } else {
+           if (gotXpg) {
+               msg = mixedXPG;
+               goto errorMsg;
+           }
+           gotSequential = 1;
+       }
+       if ((objIndex < 0) || (objIndex >= objc)) {
+           msg = badIndex[gotXpg];
+           goto errorMsg;
+       }
+
+       p = spec;
+       *p++ = '%';
+
+       gotMinus = 0;
+       sawFlag = 1;
+       do {
+           switch (ch) {
+           case '-':
+               gotMinus = 1;
+               break;
+           case '0':
+               pad = ch;
+               break;
+           case ' ':
+           case '+':
+           case '#':
+               break;
+           default:
+               sawFlag = 0;
+               continue;
+           }
+           *p++ = ch;
+           format += step;
+           step = utf8_tounicode(format, &ch);
+       } while (sawFlag);
+
+
+       width = 0;
+       if (isdigit(ch)) {
+           width = strtoul(format, &end, 10);
+           format = end;
+           step = utf8_tounicode(format, &ch);
+       } else if (ch == '*') {
+           if (objIndex >= objc - 1) {
+               msg = badIndex[gotXpg];
+               goto errorMsg;
+           }
+           if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
+               goto error;
+           }
+           if (width < 0) {
+               width = -width;
+               if (!gotMinus) {
+                   *p++ = '-';
+                   gotMinus = 1;
+               }
+           }
+           objIndex++;
+           format += step;
+           step = utf8_tounicode(format, &ch);
+       }
+
+
+       gotPrecision = precision = 0;
+       if (ch == '.') {
+           gotPrecision = 1;
+           format += step;
+           step = utf8_tounicode(format, &ch);
+       }
+       if (isdigit(ch)) {
+           precision = strtoul(format, &end, 10);
+           format = end;
+           step = utf8_tounicode(format, &ch);
+       } else if (ch == '*') {
+           if (objIndex >= objc - 1) {
+               msg = badIndex[gotXpg];
+               goto errorMsg;
+           }
+           if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
+               goto error;
+           }
+
+
+           if (precision < 0) {
+               precision = 0;
+           }
+           objIndex++;
+           format += step;
+           step = utf8_tounicode(format, &ch);
+       }
+
+
+       useShort = 0;
+       if (ch == 'h') {
+           useShort = 1;
+           format += step;
+           step = utf8_tounicode(format, &ch);
+       } else if (ch == 'l') {
+           
+           format += step;
+           step = utf8_tounicode(format, &ch);
+           if (ch == 'l') {
+               format += step;
+               step = utf8_tounicode(format, &ch);
+           }
+       }
+
+       format += step;
+       span = format;
+
+
+       if (ch == 'i') {
+           ch = 'd';
+       }
+
+       doubleType = 0;
+
+       switch (ch) {
+       case '\0':
+           msg = "format string ended in middle of field specifier";
+           goto errorMsg;
+       case 's': {
+           formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
+           formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
+           if (gotPrecision && (precision < formatted_chars)) {
+               
+               formatted_chars = precision;
+               formatted_bytes = utf8_index(formatted_buf, precision);
+           }
+           break;
+       }
+       case 'c': {
+           jim_wide code;
+
+           if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
+               goto error;
+           }
+           
+           formatted_bytes = utf8_fromunicode(spec, code);
+           formatted_buf = spec;
+           formatted_chars = 1;
+           break;
+       }
+
+       case 'e':
+       case 'E':
+       case 'f':
+       case 'g':
+       case 'G':
+           doubleType = 1;
+           
+       case 'd':
+       case 'u':
+       case 'o':
+       case 'x':
+       case 'X': {
+           jim_wide w;
+           double d;
+           int length;
+
+           
+           if (width) {
+               p += sprintf(p, "%ld", width);
+           }
+           if (gotPrecision) {
+               p += sprintf(p, ".%ld", precision);
+           }
+
+           
+           if (doubleType) {
+               if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
+                   goto error;
+               }
+               length = MAX_FLOAT_WIDTH;
+           }
+           else {
+               if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
+                   goto error;
+               }
+               length = JIM_INTEGER_SPACE;
+               if (useShort) {
+                   *p++ = 'h';
+                   if (ch == 'd') {
+                       w = (short)w;
+                   }
+                   else {
+                       w = (unsigned short)w;
+                   }
+               }
+               else {
+                   *p++ = 'l';
+#ifdef HAVE_LONG_LONG
+                   if (sizeof(long long) == sizeof(jim_wide)) {
+                       *p++ = 'l';
+                   }
+#endif
+               }
+           }
+
+           *p++ = (char) ch;
+           *p = '\0';
+
+           
+           if (width > length) {
+               length = width;
+           }
+           if (gotPrecision) {
+               length += precision;
+           }
+
+           
+           if (num_buffer_size < length + 1) {
+               num_buffer_size = length + 1;
+               num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
+           }
+
+           if (doubleType) {
+               snprintf(num_buffer, length + 1, spec, d);
+           }
+           else {
+               formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
+           }
+           formatted_chars = formatted_bytes = strlen(num_buffer);
+           formatted_buf = num_buffer;
+           break;
+       }
+
+       default: {
+           
+           spec[0] = ch;
+           spec[1] = '\0';
+           Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
+           goto error;
+       }
+       }
+
+       if (!gotMinus) {
+           while (formatted_chars < width) {
+               Jim_AppendString(interp, resultPtr, &pad, 1);
+               formatted_chars++;
+           }
+       }
+
+       Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
+
+       while (formatted_chars < width) {
+           Jim_AppendString(interp, resultPtr, &pad, 1);
+           formatted_chars++;
+       }
+
+       objIndex += gotSequential;
+    }
+    if (numBytes) {
+       Jim_AppendString(interp, resultPtr, span, numBytes);
+    }
+
+    Jim_Free(num_buffer);
+    return resultPtr;
+
+  errorMsg:
+    Jim_SetResultString(interp, msg, -1);
+  error:
+    Jim_FreeNewObj(interp, resultPtr);
+    Jim_Free(num_buffer);
+    return NULL;
+}
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
+
+
+
+#define REG_MAX_PAREN 100
+
+
+#define        END     0       
+#define        BOL     1       
+#define        EOL     2       
+#define        ANY     3       
+#define        ANYOF   4       
+#define        ANYBUT  5       
+#define        BRANCH  6       
+#define        BACK    7       
+#define        EXACTLY 8       
+#define        NOTHING 9       
+#define        REP             10      
+#define        REPMIN  11      
+#define        REPX    12      
+#define        REPXMIN 13      
+
+#define        WORDA   15      
+#define        WORDZ   16      
+#define        OPENNC  19      
+#define        OPEN    20      
+                       
+#define        CLOSE   (OPEN+REG_MAX_PAREN+1)  
+#define        CLOSE_END       (CLOSE+REG_MAX_PAREN)
+#define        CLOSENC (CLOSE-1)       
+
+#define        REG_MAGIC       0xFADED00D
+
+
+#define        OP(preg, p)     (preg->program[p])
+#define        NEXT(preg, p)   (preg->program[p + 1])
+#define        OPERAND(p)      ((p) + 2)
+
+
+
+
+#define        FAIL(R,M)       { (R)->err = (M); return (M); }
+#define        ISMULT(c)       ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
+#define        META    "^$.[()|?{+*"
+
+#define        HASWIDTH        01      
+#define        SIMPLE          02      
+#define        SPSTART         04      
+#define        WORST           0       
+
+#define MAX_REP_COUNT 1000000
+
+static int reg(regex_t *preg, int paren , int *flagp );
+static int regpiece(regex_t *preg, int *flagp );
+static int regbranch(regex_t *preg, int *flagp );
+static int regatom(regex_t *preg, int *flagp );
+static int regnode(regex_t *preg, int op );
+static int regnext(regex_t *preg, int p );
+static void regc(regex_t *preg, int b );
+static int reginsert(regex_t *preg, int op, int size, int opnd );
+static void regtail_(regex_t *preg, int p, int val, int line );
+static void regoptail(regex_t *preg, int p, int val );
+#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
+
+static int reg_range_find(const int *string, int c);
+static const char *str_find(const char *string, int c, int nocase);
+static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase);
+
+
+#ifdef DEBUG
+static int regnarrate = 0;
+static void regdump(regex_t *preg);
+static const char *regprop( int op );
+#endif
+
+
+static int str_int_len(const int *seq)
+{
+       int n = 0;
+       while (*seq++) {
+               n++;
+       }
+       return n;
+}
+
+int regcomp(regex_t *preg, const char *exp, int cflags)
+{
+       int scan;
+       int longest;
+       unsigned len;
+       int flags;
+
+#ifdef DEBUG
+       fprintf(stderr, "Compiling: '%s'\n", exp);
+#endif
+       memset(preg, 0, sizeof(*preg));
+
+       if (exp == NULL)
+               FAIL(preg, REG_ERR_NULL_ARGUMENT);
+
+       
+       preg->cflags = cflags;
+       preg->regparse = exp;
+       
+       preg->program = NULL;
+       preg->proglen = 0;
+
+       
+       preg->proglen = (strlen(exp) + 1) * 5;
+       preg->program = malloc(preg->proglen * sizeof(int));
+       if (preg->program == NULL)
+               FAIL(preg, REG_ERR_NOMEM);
+
+       regc(preg, REG_MAGIC);
+       if (reg(preg, 0, &flags) == 0) {
+               return preg->err;
+       }
+
+       
+       if (preg->re_nsub >= REG_MAX_PAREN)             
+               FAIL(preg,REG_ERR_TOO_BIG);
+
+       
+       preg->regstart = 0;     
+       preg->reganch = 0;
+       preg->regmust = 0;
+       preg->regmlen = 0;
+       scan = 1;                       
+       if (OP(preg, regnext(preg, scan)) == END) {             
+               scan = OPERAND(scan);
+
+               
+               if (OP(preg, scan) == EXACTLY) {
+                       preg->regstart = preg->program[OPERAND(scan)];
+               }
+               else if (OP(preg, scan) == BOL)
+                       preg->reganch++;
+
+               if (flags&SPSTART) {
+                       longest = 0;
+                       len = 0;
+                       for (; scan != 0; scan = regnext(preg, scan)) {
+                               if (OP(preg, scan) == EXACTLY) {
+                                       int plen = str_int_len(preg->program + OPERAND(scan));
+                                       if (plen >= len) {
+                                               longest = OPERAND(scan);
+                                               len = plen;
+                                       }
+                               }
+                       }
+                       preg->regmust = longest;
+                       preg->regmlen = len;
+               }
+       }
+
+#ifdef DEBUG
+       regdump(preg);
+#endif
+
+       return 0;
+}
+
+static int reg(regex_t *preg, int paren , int *flagp )
+{
+       int ret;
+       int br;
+       int ender;
+       int parno = 0;
+       int flags;
+
+       *flagp = HASWIDTH;      
+
+       
+       if (paren) {
+               if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
+                       
+                       preg->regparse += 2;
+                       parno = -1;
+               }
+               else {
+                       parno = ++preg->re_nsub;
+               }
+               ret = regnode(preg, OPEN+parno);
+       } else
+               ret = 0;
+
+       
+       br = regbranch(preg, &flags);
+       if (br == 0)
+               return 0;
+       if (ret != 0)
+               regtail(preg, ret, br); 
+       else
+               ret = br;
+       if (!(flags&HASWIDTH))
+               *flagp &= ~HASWIDTH;
+       *flagp |= flags&SPSTART;
+       while (*preg->regparse == '|') {
+               preg->regparse++;
+               br = regbranch(preg, &flags);
+               if (br == 0)
+                       return 0;
+               regtail(preg, ret, br); 
+               if (!(flags&HASWIDTH))
+                       *flagp &= ~HASWIDTH;
+               *flagp |= flags&SPSTART;
+       }
+
+       
+       ender = regnode(preg, (paren) ? CLOSE+parno : END);
+       regtail(preg, ret, ender);
+
+       
+       for (br = ret; br != 0; br = regnext(preg, br))
+               regoptail(preg, br, ender);
+
+       
+       if (paren && *preg->regparse++ != ')') {
+               preg->err = REG_ERR_UNMATCHED_PAREN;
+               return 0;
+       } else if (!paren && *preg->regparse != '\0') {
+               if (*preg->regparse == ')') {
+                       preg->err = REG_ERR_UNMATCHED_PAREN;
+                       return 0;
+               } else {
+                       preg->err = REG_ERR_JUNK_ON_END;
+                       return 0;
+               }
+       }
+
+       return(ret);
+}
+
+static int regbranch(regex_t *preg, int *flagp )
+{
+       int ret;
+       int chain;
+       int latest;
+       int flags;
+
+       *flagp = WORST;         
+
+       ret = regnode(preg, BRANCH);
+       chain = 0;
+       while (*preg->regparse != '\0' && *preg->regparse != ')' &&
+              *preg->regparse != '|') {
+               latest = regpiece(preg, &flags);
+               if (latest == 0)
+                       return 0;
+               *flagp |= flags&HASWIDTH;
+               if (chain == 0) {
+                       *flagp |= flags&SPSTART;
+               }
+               else {
+                       regtail(preg, chain, latest);
+               }
+               chain = latest;
+       }
+       if (chain == 0) 
+               (void) regnode(preg, NOTHING);
+
+       return(ret);
+}
+
+static int regpiece(regex_t *preg, int *flagp)
+{
+       int ret;
+       char op;
+       int next;
+       int flags;
+       int chain = 0;
+       int min;
+       int max;
+
+       ret = regatom(preg, &flags);
+       if (ret == 0)
+               return 0;
+
+       op = *preg->regparse;
+       if (!ISMULT(op)) {
+               *flagp = flags;
+               return(ret);
+       }
+
+       if (!(flags&HASWIDTH) && op != '?') {
+               preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
+               return 0;
+       }
+
+       
+       if (op == '{') {
+               char *end;
+
+               min = strtoul(preg->regparse + 1, &end, 10);
+               if (end == preg->regparse + 1) {
+                       preg->err = REG_ERR_BAD_COUNT;
+                       return 0;
+               }
+               if (*end == '}') {
+                       max = min;
+               }
+               else {
+                       preg->regparse = end;
+                       max = strtoul(preg->regparse + 1, &end, 10);
+                       if (*end != '}') {
+                               preg->err = REG_ERR_UNMATCHED_BRACES;
+                               return 0;
+                       }
+               }
+               if (end == preg->regparse + 1) {
+                       max = MAX_REP_COUNT;
+               }
+               else if (max < min || max >= 100) {
+                       preg->err = REG_ERR_BAD_COUNT;
+                       return 0;
+               }
+               if (min >= 100) {
+                       preg->err = REG_ERR_BAD_COUNT;
+                       return 0;
+               }
+
+               preg->regparse = strchr(preg->regparse, '}');
+       }
+       else {
+               min = (op == '+');
+               max = (op == '?' ? 1 : MAX_REP_COUNT);
+       }
+
+       if (preg->regparse[1] == '?') {
+               preg->regparse++;
+               next = reginsert(preg, flags & SIMPLE ? REPMIN : REPXMIN, 5, ret);
+       }
+       else {
+               next = reginsert(preg, flags & SIMPLE ? REP: REPX, 5, ret);
+       }
+       preg->program[ret + 2] = max;
+       preg->program[ret + 3] = min;
+       preg->program[ret + 4] = 0;
+
+       *flagp = (min) ? (WORST|HASWIDTH) : (WORST|SPSTART);
+
+       if (!(flags & SIMPLE)) {
+               int back = regnode(preg, BACK);
+               regtail(preg, back, ret);
+               regtail(preg, next, back);
+       }
+
+       preg->regparse++;
+       if (ISMULT(*preg->regparse)) {
+               preg->err = REG_ERR_NESTED_COUNT;
+               return 0;
+       }
+
+       return chain ? chain : ret;
+}
+
+static void reg_addrange(regex_t *preg, int lower, int upper)
+{
+       if (lower > upper) {
+               reg_addrange(preg, upper, lower);
+       }
+       
+       regc(preg, upper - lower + 1);
+       regc(preg, lower);
+}
+
+static void reg_addrange_str(regex_t *preg, const char *str)
+{
+       while (*str) {
+               reg_addrange(preg, *str, *str);
+               str++;
+       }
+}
+
+static int reg_utf8_tounicode_case(const char *s, int *uc, int upper)
+{
+       int l = utf8_tounicode(s, uc);
+       if (upper) {
+               *uc = utf8_upper(*uc);
+       }
+       return l;
+}
+
+static int hexdigitval(int c)
+{
+       if (c >= '0' && c <= '9')
+               return c - '0';
+       if (c >= 'a' && c <= 'f')
+               return c - 'a' + 10;
+       if (c >= 'A' && c <= 'F')
+               return c - 'A' + 10;
+       return -1;
+}
+
+static int parse_hex(const char *s, int n, int *uc)
+{
+       int val = 0;
+       int k;
+
+       for (k = 0; k < n; k++) {
+               int c = hexdigitval(*s++);
+               if (c == -1) {
+                       break;
+               }
+               val = (val << 4) | c;
+       }
+       if (k) {
+               *uc = val;
+       }
+       return k;
+}
+
+static int reg_decode_escape(const char *s, int *ch)
+{
+       int n;
+       const char *s0 = s;
+
+       *ch = *s++;
+
+       switch (*ch) {
+               case 'b': *ch = '\b'; break;
+               case 'e': *ch = 27; break;
+               case 'f': *ch = '\f'; break;
+               case 'n': *ch = '\n'; break;
+               case 'r': *ch = '\r'; break;
+               case 't': *ch = '\t'; break;
+               case 'v': *ch = '\v'; break;
+               case 'u':
+                       if (*s == '{') {
+                               
+                               n = parse_hex(s + 1, 6, ch);
+                               if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
+                                       s += n + 2;
+                               }
+                               else {
+                                       
+                                       *ch = 'u';
+                               }
+                       }
+                       else if ((n = parse_hex(s, 4, ch)) > 0) {
+                               s += n;
+                       }
+                       break;
+               case 'U':
+                       if ((n = parse_hex(s, 8, ch)) > 0) {
+                               s += n;
+                       }
+               case 'x':
+                       if ((n = parse_hex(s, 2, ch)) > 0) {
+                               s += n;
+                       }
+                       break;
+               case '\0':
+                       s--;
+                       *ch = '\\';
+                       break;
+       }
+       return s - s0;
+}
+
+static int regatom(regex_t *preg, int *flagp)
+{
+       int ret;
+       int flags;
+       int nocase = (preg->cflags & REG_ICASE);
+
+       int ch;
+       int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase);
+
+       *flagp = WORST;         
+
+       preg->regparse += n;
+       switch (ch) {
+       
+       case '^':
+               ret = regnode(preg, BOL);
+               break;
+       case '$':
+               ret = regnode(preg, EOL);
+               break;
+       case '.':
+               ret = regnode(preg, ANY);
+               *flagp |= HASWIDTH|SIMPLE;
+               break;
+       case '[': {
+                       const char *pattern = preg->regparse;
+
+                       if (*pattern == '^') {  
+                               ret = regnode(preg, ANYBUT);
+                               pattern++;
+                       } else
+                               ret = regnode(preg, ANYOF);
+
+                       
+                       if (*pattern == ']' || *pattern == '-') {
+                               reg_addrange(preg, *pattern, *pattern);
+                               pattern++;
+                       }
+
+                       while (*pattern && *pattern != ']') {
+                               
+                               int start;
+                               int end;
+
+                               pattern += reg_utf8_tounicode_case(pattern, &start, nocase);
+                               if (start == '\\') {
+                                       pattern += reg_decode_escape(pattern, &start);
+                                       if (start == 0) {
+                                               preg->err = REG_ERR_NULL_CHAR;
+                                               return 0;
+                                       }
+                               }
+                               if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
+                                       
+                                       pattern += utf8_tounicode(pattern, &end);
+                                       pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
+                                       if (end == '\\') {
+                                               pattern += reg_decode_escape(pattern, &end);
+                                               if (end == 0) {
+                                                       preg->err = REG_ERR_NULL_CHAR;
+                                                       return 0;
+                                               }
+                                       }
+
+                                       reg_addrange(preg, start, end);
+                                       continue;
+                               }
+                               if (start == '[') {
+                                       if (strncmp(pattern, ":alpha:]", 8) == 0) {
+                                               if ((preg->cflags & REG_ICASE) == 0) {
+                                                       reg_addrange(preg, 'a', 'z');
+                                               }
+                                               reg_addrange(preg, 'A', 'Z');
+                                               pattern += 8;
+                                               continue;
+                                       }
+                                       if (strncmp(pattern, ":alnum:]", 8) == 0) {
+                                               if ((preg->cflags & REG_ICASE) == 0) {
+                                                       reg_addrange(preg, 'a', 'z');
+                                               }
+                                               reg_addrange(preg, 'A', 'Z');
+                                               reg_addrange(preg, '0', '9');
+                                               pattern += 8;
+                                               continue;
+                                       }
+                                       if (strncmp(pattern, ":space:]", 8) == 0) {
+                                               reg_addrange_str(preg, " \t\r\n\f\v");
+                                               pattern += 8;
+                                               continue;
+                                       }
+                               }
+                               
+                               reg_addrange(preg, start, start);
+                       }
+                       regc(preg, '\0');
+
+                       if (*pattern) {
+                               pattern++;
+                       }
+                       preg->regparse = pattern;
+
+                       *flagp |= HASWIDTH|SIMPLE;
+               }
+               break;
+       case '(':
+               ret = reg(preg, 1, &flags);
+               if (ret == 0)
+                       return 0;
+               *flagp |= flags&(HASWIDTH|SPSTART);
+               break;
+       case '\0':
+       case '|':
+       case ')':
+               preg->err = REG_ERR_INTERNAL;
+               return 0;       
+       case '?':
+       case '+':
+       case '*':
+       case '{':
+               preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
+               return 0;
+       case '\\':
+               switch (*preg->regparse++) {
+               case '\0':
+                       preg->err = REG_ERR_TRAILING_BACKSLASH;
+                       return 0;
+               case '<':
+               case 'm':
+                       ret = regnode(preg, WORDA);
+                       break;
+               case '>':
+               case 'M':
+                       ret = regnode(preg, WORDZ);
+                       break;
+               case 'd':
+                       ret = regnode(preg, ANYOF);
+                       reg_addrange(preg, '0', '9');
+                       regc(preg, '\0');
+                       *flagp |= HASWIDTH|SIMPLE;
+                       break;
+               case 'w':
+                       ret = regnode(preg, ANYOF);
+                       if ((preg->cflags & REG_ICASE) == 0) {
+                               reg_addrange(preg, 'a', 'z');
+                       }
+                       reg_addrange(preg, 'A', 'Z');
+                       reg_addrange(preg, '0', '9');
+                       reg_addrange(preg, '_', '_');
+                       regc(preg, '\0');
+                       *flagp |= HASWIDTH|SIMPLE;
+                       break;
+               case 's':
+                       ret = regnode(preg, ANYOF);
+                       reg_addrange_str(preg," \t\r\n\f\v");
+                       regc(preg, '\0');
+                       *flagp |= HASWIDTH|SIMPLE;
+                       break;
+               
+               default:
+                       
+                       
+                       preg->regparse--;
+                       goto de_fault;
+               }
+               break;
+       de_fault:
+       default: {
+                       int added = 0;
+
+                       
+                       preg->regparse -= n;
+
+                       ret = regnode(preg, EXACTLY);
+
+
+                       
+                       while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
+                               n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
+                               if (ch == '\\' && preg->regparse[n]) {
+                                       if (strchr("<>mMwds", preg->regparse[n])) {
+                                               
+                                               break;
+                                       }
+                                       n += reg_decode_escape(preg->regparse + n, &ch);
+                                       if (ch == 0) {
+                                               preg->err = REG_ERR_NULL_CHAR;
+                                               return 0;
+                                       }
+                               }
+
+
+                               if (ISMULT(preg->regparse[n])) {
+                                       
+                                       if (added) {
+                                               
+                                               break;
+                                       }
+                                       
+                                       regc(preg, ch);
+                                       added++;
+                                       preg->regparse += n;
+                                       break;
+                               }
+
+                               
+                               regc(preg, ch);
+                               added++;
+                               preg->regparse += n;
+                       }
+                       regc(preg, '\0');
+
+                       *flagp |= HASWIDTH;
+                       if (added == 1)
+                               *flagp |= SIMPLE;
+                       break;
+               }
+               break;
+       }
+
+       return(ret);
+}
+
+static void reg_grow(regex_t *preg, int n)
+{
+       if (preg->p + n >= preg->proglen) {
+               preg->proglen = (preg->p + n) * 2;
+               preg->program = realloc(preg->program, preg->proglen * sizeof(int));
+       }
+}
+
+
+static int regnode(regex_t *preg, int op)
+{
+       reg_grow(preg, 2);
+
+       preg->program[preg->p++] = op;
+       preg->program[preg->p++] = 0;
+
+       
+       return preg->p - 2;
+}
+
+static void regc(regex_t *preg, int b )
+{
+       reg_grow(preg, 1);
+       preg->program[preg->p++] = b;
+}
+
+static int reginsert(regex_t *preg, int op, int size, int opnd )
+{
+       reg_grow(preg, size);
+
+       
+       memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd));
+       
+       memset(preg->program + opnd, 0, sizeof(int) * size);
+
+       preg->program[opnd] = op;
+
+       preg->p += size;
+
+       return opnd + size;
+}
+
+static void regtail_(regex_t *preg, int p, int val, int line )
+{
+       int scan;
+       int temp;
+       int offset;
+
+       
+       scan = p;
+       for (;;) {
+               temp = regnext(preg, scan);
+               if (temp == 0)
+                       break;
+               scan = temp;
+       }
+
+       if (OP(preg, scan) == BACK)
+               offset = scan - val;
+       else
+               offset = val - scan;
+
+       preg->program[scan + 1] = offset;
+}
+
+
+static void regoptail(regex_t *preg, int p, int val )
+{
+       
+       if (p != 0 && OP(preg, p) == BRANCH) {
+               regtail(preg, OPERAND(p), val);
+       }
+}
+
+
+static int regtry(regex_t *preg, const char *string );
+static int regmatch(regex_t *preg, int prog);
+static int regrepeat(regex_t *preg, int p, int max);
+
+int regexec(regex_t  *preg,  const  char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+       const char *s;
+       int scan;
+
+       
+       if (preg == NULL || preg->program == NULL || string == NULL) {
+               return REG_ERR_NULL_ARGUMENT;
+       }
+
+       
+       if (*preg->program != REG_MAGIC) {
+               return REG_ERR_CORRUPTED;
+       }
+
+#ifdef DEBUG
+       fprintf(stderr, "regexec: %s\n", string);
+       regdump(preg);
+#endif
+
+       preg->eflags = eflags;
+       preg->pmatch = pmatch;
+       preg->nmatch = nmatch;
+       preg->start = string;   
+
+       
+       for (scan = OPERAND(1); scan != 0; ) {
+               switch (OP(preg, scan)) {
+               case REP:
+               case REPMIN:
+               case REPX:
+               case REPXMIN:
+                       preg->program[scan + 4] = 0;
+                       scan += 5;
+                       break;
+
+               case ANYOF:
+               case ANYBUT:
+               case EXACTLY:
+                       scan += 2;
+                       while (preg->program[scan++]) {
+                       }
+                       break;
+
+               case END:
+                       scan = 0;
+                       break;
+
+               default:
+                       scan += 2;
+                       break;
+               }
+       }
+
+       
+       if (preg->regmust != 0) {
+               s = string;
+               while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) {
+                       if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) {
+                               break;
+                       }
+                       s++;
+               }
+               if (s == NULL)  
+                       return REG_NOMATCH;
+       }
+
+       
+       preg->regbol = string;
+
+       
+       if (preg->reganch) {
+               if (eflags & REG_NOTBOL) {
+                       
+                       goto nextline;
+               }
+               while (1) {
+                       if (regtry(preg, string)) {
+                               return REG_NOERROR;
+                       }
+                       if (*string) {
+nextline:
+                               if (preg->cflags & REG_NEWLINE) {
+                                       
+                                       string = strchr(string, '\n');
+                                       if (string) {
+                                               preg->regbol = ++string;
+                                               continue;
+                                       }
+                               }
+                       }
+                       return REG_NOMATCH;
+               }
+       }
+
+       
+       s = string;
+       if (preg->regstart != '\0') {
+               
+               while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) {
+                       if (regtry(preg, s))
+                               return REG_NOERROR;
+                       s++;
+               }
+       }
+       else
+               
+               while (1) {
+                       if (regtry(preg, s))
+                               return REG_NOERROR;
+                       if (*s == '\0') {
+                               break;
+                       }
+                       else {
+                               int c;
+                               s += utf8_tounicode(s, &c);
+                       }
+               }
+
+       
+       return REG_NOMATCH;
+}
+
+                       
+static int regtry( regex_t *preg, const char *string )
+{
+       int i;
+
+       preg->reginput = string;
+
+       for (i = 0; i < preg->nmatch; i++) {
+               preg->pmatch[i].rm_so = -1;
+               preg->pmatch[i].rm_eo = -1;
+       }
+       if (regmatch(preg, 1)) {
+               preg->pmatch[0].rm_so = string - preg->start;
+               preg->pmatch[0].rm_eo = preg->reginput - preg->start;
+               return(1);
+       } else
+               return(0);
+}
+
+static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase)
+{
+       const char *s = string;
+       while (proglen && *s) {
+               int ch;
+               int n = reg_utf8_tounicode_case(s, &ch, nocase);
+               if (ch != *prog) {
+                       return -1;
+               }
+               prog++;
+               s += n;
+               proglen--;
+       }
+       if (proglen == 0) {
+               return s - string;
+       }
+       return -1;
+}
+
+static int reg_range_find(const int *range, int c)
+{
+       while (*range) {
+               
+               if (c >= range[1] && c <= (range[0] + range[1] - 1)) {
+                       return 1;
+               }
+               range += 2;
+       }
+       return 0;
+}
+
+static const char *str_find(const char *string, int c, int nocase)
+{
+       if (nocase) {
+               
+               c = utf8_upper(c);
+       }
+       while (*string) {
+               int ch;
+               int n = reg_utf8_tounicode_case(string, &ch, nocase);
+               if (c == ch) {
+                       return string;
+               }
+               string += n;
+       }
+       return NULL;
+}
+
+static int reg_iseol(regex_t *preg, int ch)
+{
+       if (preg->cflags & REG_NEWLINE) {
+               return ch == '\0' || ch == '\n';
+       }
+       else {
+               return ch == '\0';
+       }
+}
+
+static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin)
+{
+       int nextch = '\0';
+       const char *save;
+       int no;
+       int c;
+
+       int max = preg->program[scan + 2];
+       int min = preg->program[scan + 3];
+       int next = regnext(preg, scan);
+
+       if (OP(preg, next) == EXACTLY) {
+               nextch = preg->program[OPERAND(next)];
+       }
+       save = preg->reginput;
+       no = regrepeat(preg, scan + 5, max);
+       if (no < min) {
+               return 0;
+       }
+       if (matchmin) {
+               
+               max = no;
+               no = min;
+       }
+       
+       while (1) {
+               if (matchmin) {
+                       if (no > max) {
+                               break;
+                       }
+               }
+               else {
+                       if (no < min) {
+                               break;
+                       }
+               }
+               preg->reginput = save + utf8_index(save, no);
+               reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
+               
+               if (reg_iseol(preg, nextch) || c == nextch) {
+                       if (regmatch(preg, next)) {
+                               return(1);
+                       }
+               }
+               if (matchmin) {
+                       
+                       no++;
+               }
+               else {
+                       
+                       no--;
+               }
+       }
+       return(0);
+}
+
+static int regmatchrepeat(regex_t *preg, int scan, int matchmin)
+{
+       int *scanpt = preg->program + scan;
+
+       int max = scanpt[2];
+       int min = scanpt[3];
+
+       
+       if (scanpt[4] < min) {
+               
+               scanpt[4]++;
+               if (regmatch(preg, scan + 5)) {
+                       return 1;
+               }
+               scanpt[4]--;
+               return 0;
+       }
+       if (scanpt[4] > max) {
+               return 0;
+       }
+
+       if (matchmin) {
+               
+               if (regmatch(preg, regnext(preg, scan))) {
+                       return 1;
+               }
+               
+               scanpt[4]++;
+               if (regmatch(preg, scan + 5)) {
+                       return 1;
+               }
+               scanpt[4]--;
+               return 0;
+       }
+       
+       if (scanpt[4] < max) {
+               scanpt[4]++;
+               if (regmatch(preg, scan + 5)) {
+                       return 1;
+               }
+               scanpt[4]--;
+       }
+       
+       return regmatch(preg, regnext(preg, scan));
+}
+
+
+static int regmatch(regex_t *preg, int prog)
+{
+       int scan;       
+       int next;               
+
+       scan = prog;
+
+#ifdef DEBUG
+       if (scan != 0 && regnarrate)
+               fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+       while (scan != 0) {
+               int n;
+               int c;
+#ifdef DEBUG
+               if (regnarrate) {
+                       fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); 
+               }
+#endif
+               next = regnext(preg, scan);
+               n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
+
+               switch (OP(preg, scan)) {
+               case BOL:
+                       if (preg->reginput != preg->regbol)
+                               return(0);
+                       break;
+               case EOL:
+                       if (!reg_iseol(preg, c)) {
+                               return(0);
+                       }
+                       break;
+               case WORDA:
+                       
+                       if ((!isalnum(UCHAR(c))) && c != '_')
+                               return(0);
+                       
+                       if (preg->reginput > preg->regbol &&
+                               (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_'))
+                               return(0);
+                       break;
+               case WORDZ:
+                       
+                       if (preg->reginput > preg->regbol) {
+                               
+                               if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') {
+                                       c = preg->reginput[-1];
+                                       
+                                       if (isalnum(UCHAR(c)) || c == '_') {
+                                               break;
+                                       }
+                               }
+                       }
+                       
+                       return(0);
+
+               case ANY:
+                       if (reg_iseol(preg, c))
+                               return 0;
+                       preg->reginput += n;
+                       break;
+               case EXACTLY: {
+                               int opnd;
+                               int len;
+                               int slen;
+
+                               opnd = OPERAND(scan);
+                               len = str_int_len(preg->program + opnd);
+
+                               slen = prefix_cmp(preg->program + opnd, len, preg->reginput, preg->cflags & REG_ICASE);
+                               if (slen < 0) {
+                                       return(0);
+                               }
+                               preg->reginput += slen;
+                       }
+                       break;
+               case ANYOF:
+                       if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) == 0) {
+                               return(0);
+                       }
+                       preg->reginput += n;
+                       break;
+               case ANYBUT:
+                       if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) != 0) {
+                               return(0);
+                       }
+                       preg->reginput += n;
+                       break;
+               case NOTHING:
+                       break;
+               case BACK:
+                       break;
+               case BRANCH: {
+                               const char *save;
+
+                               if (OP(preg, next) != BRANCH)           
+                                       next = OPERAND(scan);   
+                               else {
+                                       do {
+                                               save = preg->reginput;
+                                               if (regmatch(preg, OPERAND(scan))) {
+                                                       return(1);
+                                               }
+                                               preg->reginput = save;
+                                               scan = regnext(preg, scan);
+                                       } while (scan != 0 && OP(preg, scan) == BRANCH);
+                                       return(0);
+                                       
+                               }
+                       }
+                       break;
+               case REP:
+               case REPMIN:
+                       return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN);
+
+               case REPX:
+               case REPXMIN:
+                       return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
+
+               case END:
+                       return(1);      
+                       break;
+
+               case OPENNC:
+               case CLOSENC:
+                       if (regmatch(preg, next)) {
+                               return 1;
+                       }
+                       return 0;
+
+               default:
+                       if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
+                               const char *save;
+
+                               save = preg->reginput;
+
+                               if (regmatch(preg, next)) {
+                                       int no;
+                                       if (OP(preg, scan) < CLOSE) {
+                                               no = OP(preg, scan) - OPEN;
+                                               if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
+                                                       preg->pmatch[no].rm_so = save - preg->start;
+                                               }
+                                       }
+                                       else {
+                                               no = OP(preg, scan) - CLOSE;
+                                               if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
+                                                       preg->pmatch[no].rm_eo = save - preg->start;
+                                               }
+                                       }
+                                       return(1);
+                               } else
+                                       return(0);
+                       }
+                       return REG_ERR_INTERNAL;
+               }
+
+               scan = next;
+       }
+
+       return REG_ERR_INTERNAL;
+}
+
+static int regrepeat(regex_t *preg, int p, int max)
+{
+       int count = 0;
+       const char *scan;
+       int opnd;
+       int ch;
+       int n;
+
+       scan = preg->reginput;
+       opnd = OPERAND(p);
+       switch (OP(preg, p)) {
+       case ANY:
+               
+               while (!reg_iseol(preg, *scan) && count < max) {
+                       count++;
+                       scan++;
+               }
+               break;
+       case EXACTLY:
+               while (count < max) {
+                       n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE);
+                       if (preg->program[opnd] != ch) {
+                               break;
+                       }
+                       count++;
+                       scan += n;
+               }
+               break;
+       case ANYOF:
+               while (count < max) {
+                       n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE);
+                       if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) == 0) {
+                               break;
+                       }
+                       count++;
+                       scan += n;
+               }
+               break;
+       case ANYBUT:
+               while (count < max) {
+                       n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE);
+                       if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) != 0) {
+                               break;
+                       }
+                       count++;
+                       scan += n;
+               }
+               break;
+       default:                
+               preg->err = REG_ERR_INTERNAL;
+               count = 0;      
+               break;
+       }
+       preg->reginput = scan;
+
+       return(count);
+}
+
+static int regnext(regex_t *preg, int p )
+{
+       int offset;
+
+       offset = NEXT(preg, p);
+
+       if (offset == 0)
+               return 0;
+
+       if (OP(preg, p) == BACK)
+               return(p-offset);
+       else
+               return(p+offset);
+}
+
+
+size_t regerror(int errcode, const regex_t *preg, char *errbuf,  size_t errbuf_size)
+{
+       static const char *error_strings[] = {
+               "success",
+               "no match",
+               "bad pattern",
+               "null argument",
+               "unknown error",
+               "too big",
+               "out of memory",
+               "too many ()",
+               "parentheses () not balanced",
+               "braces {} not balanced",
+               "invalid repetition count(s)",
+               "extra characters",
+               "*+ of empty atom",
+               "nested count",
+               "internal error",
+               "count follows nothing",
+               "trailing backslash",
+               "corrupted program",
+               "contains null char",
+       };
+       const char *err;
+
+       if (errcode < 0 || errcode >= REG_ERR_NUM) {
+               err = "Bad error code";
+       }
+       else {
+               err = error_strings[errcode];
+       }
+
+       return snprintf(errbuf, errbuf_size, "%s", err);
+}
+
+void regfree(regex_t *preg)
+{
+       free(preg->program);
+}
+
+#endif
+
+#if defined(_WIN32) || defined(WIN32)
+#ifndef STRICT
+#define STRICT
+#endif
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#if defined(HAVE_DLOPEN_COMPAT)
+void *dlopen(const char *path, int mode)
+{
+    JIM_NOTUSED(mode);
+
+    return (void *)LoadLibraryA(path);
+}
+
+int dlclose(void *handle)
+{
+    FreeLibrary((HANDLE)handle);
+    return 0;
+}
+
+void *dlsym(void *handle, const char *symbol)
+{
+    return GetProcAddress((HMODULE)handle, symbol);
+}
+
+char *dlerror(void)
+{
+    static char msg[121];
+    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+                   LANG_NEUTRAL, msg, sizeof(msg) - 1, NULL);
+    return msg;
+}
+#endif
+
+#ifdef _MSC_VER
+
+#include <sys/timeb.h>
+
+
+int gettimeofday(struct timeval *tv, void *unused)
+{
+    struct _timeb tb;
+
+    _ftime(&tb);
+    tv->tv_sec = tb.time;
+    tv->tv_usec = tb.millitm * 1000;
+
+    return 0;
+}
+
+
+DIR *opendir(const char *name)
+{
+    DIR *dir = 0;
+
+    if (name && name[0]) {
+        size_t base_length = strlen(name);
+        const char *all =       
+            strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+        if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
+            (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
+            strcat(strcpy(dir->name, name), all);
+
+            if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
+                dir->result.d_name = 0;
+            else {              
+                Jim_Free(dir->name);
+                Jim_Free(dir);
+                dir = 0;
+            }
+        }
+        else {                  
+            Jim_Free(dir);
+            dir = 0;
+            errno = ENOMEM;
+        }
+    }
+    else {
+        errno = EINVAL;
+    }
+    return dir;
+}
+
+int closedir(DIR * dir)
+{
+    int result = -1;
+
+    if (dir) {
+        if (dir->handle != -1)
+            result = _findclose(dir->handle);
+        Jim_Free(dir->name);
+        Jim_Free(dir);
+    }
+    if (result == -1)           
+        errno = EBADF;
+    return result;
+}
+
+struct dirent *readdir(DIR * dir)
+{
+    struct dirent *result = 0;
+
+    if (dir && dir->handle != -1) {
+        if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) {
+            result = &dir->result;
+            result->d_name = dir->info.name;
+        }
+    }
+    else {
+        errno = EBADF;
+    }
+    return result;
+}
+#endif
+#endif
+#ifndef JIM_BOOTSTRAP_LIB_ONLY
+#include <errno.h>
+#include <string.h>
+
+
+#ifdef USE_LINENOISE
+#include <unistd.h>
+#include "linenoise.h"
+#else
+#define MAX_LINE_LEN 512
+#endif
+
+char *Jim_HistoryGetline(const char *prompt)
+{
+#ifdef USE_LINENOISE
+    return linenoise(prompt);
+#else
+    char *line = malloc(MAX_LINE_LEN);
+
+    fputs(prompt, stdout);
+    fflush(stdout);
+
+    if (fgets(line, MAX_LINE_LEN, stdin) == NULL) {
+        free(line);
+        return NULL;
+    }
+    return line;
+#endif
+}
+
+void Jim_HistoryLoad(const char *filename)
+{
+#ifdef USE_LINENOISE
+    linenoiseHistoryLoad(filename);
+#endif
+}
+
+void Jim_HistoryAdd(const char *line)
+{
+#ifdef USE_LINENOISE
+    linenoiseHistoryAdd(line);
+#endif
+}
+
+void Jim_HistorySave(const char *filename)
+{
+#ifdef USE_LINENOISE
+    linenoiseHistorySave(filename);
+#endif
+}
+
+void Jim_HistoryShow(void)
+{
+#ifdef USE_LINENOISE
+    
+    int i;
+    int len;
+    char **history = linenoiseHistory(&len);
+    for (i = 0; i < len; i++) {
+        printf("%4d %s\n", i + 1, history[i]);
+    }
+#endif
+}
+
+int Jim_InteractivePrompt(Jim_Interp *interp)
+{
+    int retcode = JIM_OK;
+    char *history_file = NULL;
+#ifdef USE_LINENOISE
+    const char *home;
+
+    home = getenv("HOME");
+    if (home && isatty(STDIN_FILENO)) {
+        int history_len = strlen(home) + sizeof("/.jim_history");
+        history_file = Jim_Alloc(history_len);
+        snprintf(history_file, history_len, "%s/.jim_history", home);
+        Jim_HistoryLoad(history_file);
+    }
+#endif
+
+    printf("Welcome to Jim version %d.%d" JIM_NL,
+        JIM_VERSION / 100, JIM_VERSION % 100);
+    Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
+
+    while (1) {
+        Jim_Obj *scriptObjPtr;
+        const char *result;
+        int reslen;
+        char prompt[20];
+        const char *str;
+
+        if (retcode != 0) {
+            const char *retcodestr = Jim_ReturnCode(retcode);
+
+            if (*retcodestr == '?') {
+                snprintf(prompt, sizeof(prompt) - 3, "[%d] ", retcode);
+            }
+            else {
+                snprintf(prompt, sizeof(prompt) - 3, "[%s] ", retcodestr);
+            }
+        }
+        else {
+            prompt[0] = '\0';
+        }
+        strcat(prompt, ". ");
+
+        scriptObjPtr = Jim_NewStringObj(interp, "", 0);
+        Jim_IncrRefCount(scriptObjPtr);
+        while (1) {
+            char state;
+            int len;
+            char *line;
+
+            line = Jim_HistoryGetline(prompt);
+            if (line == NULL) {
+                if (errno == EINTR) {
+                    continue;
+                }
+                Jim_DecrRefCount(interp, scriptObjPtr);
+                retcode = JIM_OK;
+                goto out;
+            }
+            if (Jim_Length(scriptObjPtr) != 0) {
+                Jim_AppendString(interp, scriptObjPtr, "\n", 1);
+            }
+            Jim_AppendString(interp, scriptObjPtr, line, -1);
+            free(line);
+            str = Jim_GetString(scriptObjPtr, &len);
+            if (len == 0) {
+                continue;
+            }
+            if (Jim_ScriptIsComplete(str, len, &state))
+                break;
+
+            snprintf(prompt, sizeof(prompt), "%c> ", state);
+        }
+#ifdef USE_LINENOISE
+        if (strcmp(str, "h") == 0) {
+            
+            Jim_HistoryShow();
+            Jim_DecrRefCount(interp, scriptObjPtr);
+            continue;
+        }
+
+        Jim_HistoryAdd(Jim_String(scriptObjPtr));
+        if (history_file) {
+            Jim_HistorySave(history_file);
+        }
+#endif
+        retcode = Jim_EvalObj(interp, scriptObjPtr);
+        Jim_DecrRefCount(interp, scriptObjPtr);
+
+        if (retcode == JIM_EXIT) {
+            retcode = JIM_EXIT;
+            break;
+        }
+        if (retcode == JIM_ERR) {
+            Jim_MakeErrorMessage(interp);
+        }
+        result = Jim_GetString(Jim_GetResult(interp), &reslen);
+        if (reslen) {
+            printf("%s\n", result);
+        }
+    }
+  out:
+    Jim_Free(history_file);
+    return retcode;
+}
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+extern int Jim_initjimshInit(Jim_Interp *interp);
+
+static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
+{
+    int n;
+    Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
+
+    
+    for (n = 0; n < argc; n++) {
+        Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1);
+
+        Jim_ListAppendElement(interp, listObj, obj);
+    }
+
+    Jim_SetVariableStr(interp, "argv", listObj);
+    Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
+}
+
+int main(int argc, char *const argv[])
+{
+    int retcode;
+    Jim_Interp *interp;
+
+    if (argc > 1 && strcmp(argv[1], "--version") == 0) {
+        printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
+        return 0;
+    }
+
+    
+    interp = Jim_CreateInterp();
+    Jim_RegisterCoreCommands(interp);
+
+    
+    if (Jim_InitStaticExtensions(interp) != JIM_OK) {
+        Jim_MakeErrorMessage(interp);
+        fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
+    }
+
+    Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
+    Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
+    retcode = Jim_initjimshInit(interp);
+
+    if (argc == 1) {
+        if (retcode == JIM_ERR) {
+            Jim_MakeErrorMessage(interp);
+            fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
+        }
+        if (retcode != JIM_EXIT) {
+            JimSetArgv(interp, 0, NULL);
+            retcode = Jim_InteractivePrompt(interp);
+        }
+    }
+    else {
+        if (argc > 2 && strcmp(argv[1], "-e") == 0) {
+            JimSetArgv(interp, argc - 3, argv + 3);
+            retcode = Jim_Eval(interp, argv[2]);
+            if (retcode != JIM_ERR) {
+                printf("%s\n", Jim_String(Jim_GetResult(interp)));
+            }
+        }
+        else {
+            Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
+            JimSetArgv(interp, argc - 2, argv + 2);
+            retcode = Jim_EvalFile(interp, argv[1]);
+        }
+        if (retcode == JIM_ERR) {
+            Jim_MakeErrorMessage(interp);
+            fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
+        }
+    }
+    if (retcode == JIM_EXIT) {
+        retcode = Jim_GetExitCode(interp);
+    }
+    else if (retcode == JIM_ERR) {
+        retcode = 1;
+    }
+    else {
+        retcode = 0;
+    }
+    Jim_FreeInterp(interp);
+    return retcode;
+}
+#endif
diff --git a/jim/autosetup/local.tcl b/jim/autosetup/local.tcl
new file mode 100755 (executable)
index 0000000..36aff86
--- /dev/null
@@ -0,0 +1,194 @@
+# The complex extension checking is done here.
+
+global withinfo
+global extdb
+
+# Final determination of module status
+dict set extdb status {}
+
+# Returns 1 if the extension has the attribute
+proc ext-has {ext attr} {
+    expr {$attr in [dict get $::extdb attrs $ext]}
+}
+
+# Returns an entry from the extension 'info' table, or $default otherwise
+proc ext-get {ext key {default {}}} {
+    if {[dict exists $::extdb info $ext $key]} {
+        return [dict get $::extdb info $ext $key]
+    } else {
+        return $default
+    }
+}
+
+# Set the status of the extension to the given value, and returns the value
+proc ext-set-status {ext value} {
+    dict set ::extdb status $ext $value
+    return $value
+}
+
+# Returns the status of the extension, or ? if unknown
+proc ext-get-status {ext} {
+    if {[dict exists $::extdb status $ext]} {
+        return [dict get $::extdb status $ext]
+    }
+    return ?
+}
+
+proc check-extension-status {ext required} {
+    global withinfo
+
+    set status [ext-get-status $ext]
+
+    if {$ext in $withinfo(without)} {
+        # Disabled without further ado
+        msg-result "Extension $ext...disabled"
+        return [ext-set-status $ext n]
+    }
+
+    if {$status in {m y n}} {
+        return $status
+    }
+
+    # required is "required" if this extension *must* be enabled
+    # required is "wanted" if it is not fatal for this extension
+    # not to be enabled
+
+    array set depinfo {m 0 y 0 n 0}
+
+    # Check direct dependencies
+    if [ext-get $ext check 1] {
+        # "check" conditions are met
+    } else {
+        # not met
+        incr depinfo(n)
+    }
+
+    if {$depinfo(n) == 0} {
+        # Now extension dependencies
+        foreach i [ext-get $ext dep] {
+            set status [check-extension-status $i $required]
+            #puts "$ext: dep $i $required => $status"
+            incr depinfo($status)
+            if {$depinfo(n)} {
+                break
+            }
+        }
+    }
+
+    #parray depinfo
+
+    if {$depinfo(n)} {
+        msg-checking "Extension $ext..."
+        if {$required eq "required"} {
+            user-error "dependencies not met"
+        }
+        msg-result "disabled (dependencies)"
+        return [ext-set-status $ext n]
+    }
+
+    # Selected as a module?
+    if {$ext in $withinfo(mod)} {
+        if {[ext-has $ext tcl]} {
+            # Easy, a Tcl module
+            msg-result "Extension $ext...tcl"
+        } elseif {[ext-has $ext static]} {
+            user-error "Extension $ext can't be a module"
+        } else {
+            msg-result "Extension $ext...module"
+            foreach i [ext-get $ext libdep] {
+                define-append LDLIBS_$ext [get-define $i ""]
+            }
+        }
+        return [ext-set-status $ext m]
+    }
+
+    # Selected as a static extension?
+    if {[ext-has $ext shared]} {
+        user-error "Extension $ext can only be selected as a module"
+    } elseif {$ext in $withinfo(ext) || $required eq "$required"} {
+        msg-result "Extension $ext...enabled"
+    } elseif {$ext in $withinfo(maybe)} {
+        msg-result "Extension $ext...enabled (default)"
+    } else {
+        # Could be selected, but isn't (yet)
+        return [ext-set-status $ext x]
+    }
+    foreach i [ext-get $ext libdep] {
+        define-append LDLIBS [get-define $i ""]
+    }
+    return [ext-set-status $ext y]
+}
+
+# Examines the user options (the $withinfo array)
+# and the extension database ($extdb) to determine
+# what is selected, and in what way.
+#
+# The results are available via ext-get-status
+# And a dictionary is returned containing four keys:
+#   static-c     extensions which are static C
+#   static-tcl   extensions which are static Tcl
+#   module-c     extensions which are C modules
+#   module-tcl   extensions which are Tcl modules
+proc check-extensions {} {
+    global extdb withinfo
+
+    # Check valid extension names
+    foreach i [concat $withinfo(ext) $withinfo(mod)] {
+        if {![dict exists $extdb attrs $i]} {
+            user-error "Unknown extension: $i"
+        }
+    }
+
+    set extlist [lsort [dict keys [dict get $extdb attrs]]]
+
+    set withinfo(maybe) {}
+
+    # Now work out the default status. We have.
+    # normal case, include !optional if possible
+    # --without=default, don't include optional
+    if {$withinfo(nodefault)} {
+        lappend withinfo(maybe) stdlib
+    } else {
+        foreach i $extlist {
+            if {![ext-has $i optional]} {
+                lappend withinfo(maybe) $i
+            }
+        }
+    }
+
+    foreach i $extlist {
+        define LDLIBS_$i ""
+    }
+
+    foreach i [concat $withinfo(ext) $withinfo(mod)] {
+        check-extension-status $i required
+    }
+    foreach i $withinfo(maybe) {
+        check-extension-status $i wanted
+    }
+
+    array set extinfo {static-c {} static-tcl {} module-c {} module-tcl {}}
+
+    foreach i $extlist {
+        set status [ext-get-status $i]
+        set tcl [ext-has $i tcl]
+        switch $status,$tcl {
+            y,1 {
+                define jim_ext_$i
+                lappend extinfo(static-tcl) $i
+            }
+            y,0 {
+                define jim_ext_$i
+                lappend extinfo(static-c) $i
+                # If there are any static C++ extensions, jimsh must be linked using
+                # the C++ compiler
+                if {[ext-has $i cpp]} {
+                    define HAVE_CXX_EXTENSIONS
+                }
+            }
+            m,1 { lappend extinfo(module-tcl) $i }
+            m,0 { lappend extinfo(module-c) $i }
+        }
+    }
+    return [array get extinfo]
+}
old mode 100644 (file)
new mode 100755 (executable)
index f05d05b..2712e39
@@ -217,7 +217,8 @@ if {$host eq ""} {
 }
 define cross [get-env CROSS $cross]
 
-set prefix [opt-val prefix /usr/local]
+# Do "define defaultprefix myvalue" to set the default prefix *before* the first "use"
+set prefix [opt-val prefix [get-define defaultprefix /usr/local]]
 
 # These are for compatibility with autoconf
 define target [get-define host]
@@ -254,7 +255,7 @@ define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
 
 # Windows vs. non-Windows
 switch -glob -- [get-define host] {
-       *-*-ming* - *-*-cygwin {
+       *-*-ming* - *-*-cygwin - *-*-msys {
                define-feature windows
                define EXEEXT .exe
        }
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/jim/bench.tcl b/jim/bench.tcl
new file mode 100755 (executable)
index 0000000..f39bef1
--- /dev/null
@@ -0,0 +1,580 @@
+set batchmode 0
+set benchmarks {}
+
+proc bench {title script} {
+    global benchmarks batchmode
+
+    set Title [string range "$title                     " 0 20]
+
+    set failed [catch {time $script} res]
+    if {$failed} {
+        if {!$batchmode} {puts "$Title - This test can't run on this interpreter ($res)"}
+        lappend benchmarks $title F
+    } else {
+        set t [expr [lindex $res 0] / 1000]
+        lappend benchmarks $title $t
+        set ts "          $t"
+        set ts [string range $ts [expr {[string length $ts]-10}] end]
+        if {!$batchmode} {puts "$Title -$ts ms per iteration"}
+    }
+    catch { collect }
+}
+
+### BUSY LOOP ##################################################################
+
+proc whilebusyloop {} {
+    set i 0
+    while {$i < 1850000} {
+        set a 2
+       incr i
+    }
+}
+
+proc forbusyloop {} {
+    for {set i 0} {$i < 1850000} {incr i} {
+        set a 2
+    }
+}
+
+### FIBONACCI ##################################################################
+
+proc fibonacci {x} {
+    if {$x <= 1} {
+       expr 1
+    } else {
+       expr {[fibonacci [expr {$x-1}]] + [fibonacci [expr {$x-2}]]}
+    }
+}
+
+### HEAPSORT ###################################################################
+
+set IM 139968
+set IA   3877
+set IC  29573
+
+set last 42
+
+proc make_gen_random {} {
+    global IM IA IC
+    set params [list IM $IM IA $IA IC $IC]
+    set body [string map $params {
+        global last
+        expr {($max * [set last [expr {($last * IA + IC) % IM}]]) / IM}
+    }]
+    proc gen_random {max} $body
+}
+
+proc heapsort {ra_name} {
+    upvar 1 $ra_name ra
+    set n [llength $ra]
+    set l [expr {$n / 2}]
+    set ir [expr {$n - 1}]
+    while 1 {
+        if {$l} {
+            set rra [lindex $ra [incr l -1]]
+        } else {
+           set rra [lindex $ra $ir]
+           lset ra $ir [lindex $ra 0]
+           if {[incr ir -1] == 0} {
+                lset ra 0 $rra
+               break
+            }
+        }
+       set i $l
+       set j [expr {(2 * $l) + 1}]
+        while {$j <= $ir} {
+           set tmp [lindex $ra $j]
+           if {$j < $ir} {
+               if {$tmp < [lindex $ra [expr {$j + 1}]]} {
+                   set tmp [lindex $ra [incr j]]
+               }
+           }
+            if {$rra >= $tmp} {
+               break
+           }
+           lset ra $i $tmp
+           incr j [set i $j]
+        }
+        lset ra $i $rra
+    }
+}
+
+proc heapsort_main {} {
+    set n 6100
+    make_gen_random
+
+    set data {}
+    for {set i 1} {$i <= $n} {incr i} {
+       lappend data [gen_random 1.0]
+    }
+    heapsort data
+}
+
+### SIEVE ######################################################################
+
+proc sieve {num} {
+    while {$num > 0} {
+       incr num -1
+       set count 0
+       for {set i 2} {$i <= 8192} {incr i} {
+           set flags($i) 1
+       }
+       for {set i 2} {$i <= 8192} {incr i} {
+           if {$flags($i) == 1} {
+               # remove all multiples of prime: i
+               for {set k [expr {$i+$i}]} {$k <= 8192} {incr k $i} {
+                   set flags($k) 0
+               }
+               incr count
+           }
+       }
+    }
+    return $count
+}
+
+proc sieve_dict {num} {
+    while {$num > 0} {
+       incr num -1
+       set count 0
+       for {set i 2} {$i <= 8192} {incr i} {
+           dict set flags $i 1
+       }
+       for {set i 2} {$i <= 8192} {incr i} {
+           if {[dict get $flags $i] == 1} {
+               # remove all multiples of prime: i
+               for {set k [expr {$i+$i}]} {$k <= 8192} {incr k $i} {
+                   dict set flags $k 0
+               }
+               incr count
+           }
+       }
+    }
+    return $count
+}
+
+### ARY ########################################################################
+
+proc ary n {
+    for {set i 0} {$i < $n} {incr i} {
+       set x($i) $i
+    }
+    set last [expr {$n - 1}]
+    for {set j $last} {$j >= 0} {incr j -1} {
+       set y($j) $x($j)
+    }
+}
+
+proc ary_dict n {
+    for {set i 0} {$i < $n} {incr i} {
+       dict set x $i $i
+    }
+    set last [expr {$n - 1}]
+    for {set j $last} {$j >= 0} {incr j -1} {
+       dict set y $j $x($j)
+    }
+}
+
+proc ary_static n {
+    for {set i 0} {$i < $n} {incr i} {
+        set a(b) $i
+        set a(c) $i
+    }
+}
+
+### REPEAT #####################################################################
+
+proc repeat {n body} {
+    for {set i 0} {$i < $n} {incr i} {
+       uplevel 1 $body
+    }
+}
+
+proc use_repeat {} {
+    set x 0
+    repeat {1000000} {incr x}
+}
+
+### UPVAR ######################################################################
+
+proc myincr varname {
+    upvar 1 $varname x
+    incr x
+}
+
+proc upvartest {} {
+    set y 0
+    for {set x 0} {$x < 100000} {myincr x} {
+       myincr y
+    }
+}
+
+### NESTED LOOPS ###############################################################
+
+proc nestedloops {} {
+    set n 10
+    set x 0
+    incr n 1
+    set a $n
+    while {[incr a -1]} {
+       set b $n
+       while {[incr b -1]} {
+           set c $n
+           while {[incr c -1]} {
+               set d $n
+               while {[incr d -1]} {
+                   set e $n
+                   while {[incr e -1]} {
+                       set f $n
+                       while {[incr f -1]} {
+                           incr x
+                       }
+                   }
+               }
+           }
+       }
+    }
+}
+
+### ROTATE #####################################################################
+
+proc rotate {count} {
+    set v 1
+    for {set n 0} {$n < $count} {incr n} {
+       set v [expr {$v <<< 1}]
+    }
+}
+
+### DYNAMICALLY GENERATED CODE #################################################
+
+proc dyncode {} {
+    for {set i 0} {$i < 100000} {incr i} {
+        set script "lappend foo $i"
+        eval $script
+    }
+}
+
+proc dyncode_list {} {
+    for {set i 0} {$i < 100000} {incr i} {
+        set script [list lappend foo $i]
+        eval $script
+    }
+}
+
+### PI DIGITS ##################################################################
+
+proc pi_digits {N} {
+ set n [expr {$N * 3}]
+ set e 0
+ set f {}
+ for { set b 0 } { $b <= $n } { incr b } {
+     lappend f 2000
+ }
+ for { set c $n } { $c > 0 } { incr c -14 } {
+     set d 0
+     set g [expr { $c * 2 }]
+     set b $c
+     while 1 {
+         incr d [expr { [lindex $f $b] * 10000 }]
+         lset f $b [expr {$d % [incr g -1]}]
+         set d [expr { $d / $g }]
+         incr g -1
+         if { [incr b -1] == 0 } break
+         set d [expr { $d * $b }]
+     }
+     append result [string range 0000[expr { $e + $d / 10000 }] end-3 end]
+     set e [expr { $d % 10000 }]
+ }
+ #puts $result
+}
+
+### EXPAND #####################################################################
+
+proc expand {} {
+    set a [list a b c d e f]
+    for {set i 0} {$i < 100000} {incr i} {
+        lappend b {*}$a
+    }
+}
+
+### MINLOOPS ###################################################################
+
+proc miniloops {} {
+    for {set i 0} {$i < 100000} {incr i} {
+        set sum 0
+        for {set j 0} {$j < 10} {incr j} {
+            # something of more or less real
+            incr sum $j
+        }
+    }
+}
+
+### wiki.tcl.tk/8566 ###########################################################
+
+ # Internal procedure that indexes into the 2-dimensional array t,
+ # which corresponds to the sequence y, looking for the (i,j)th element.
+
+ proc Index { t y i j } {
+     set indx [expr { ([llength $y] + 1) * ($i + 1) + ($j + 1) }]
+     return [lindex $t $indx]
+ }
+
+ # Internal procedure that implements Levenshtein to derive the longest
+ # common subsequence of two lists x and y.
+
+ proc ComputeLCS { x y } {
+     set t [list]
+     for { set i -1 } { $i < [llength $y] } { incr i } {
+         lappend t 0
+     }
+     for { set i 0 } { $i < [llength $x] } { incr i } {
+         lappend t 0
+         for { set j 0 } { $j < [llength $y] } { incr j } {
+             if { [string equal [lindex $x $i] [lindex $y $j]] } {
+                 set lastT [Index $t $y [expr { $i - 1 }] [expr {$j - 1}]]
+                 set nextT [expr {$lastT + 1}]
+             } else {
+                 set lastT1 [Index $t $y $i [expr { $j - 1 }]]
+                 set lastT2 [Index $t $y [expr { $i - 1 }] $j]
+                 if { $lastT1 > $lastT2 } {
+                     set nextT $lastT1
+                 } else {
+                     set nextT $lastT2
+                 }
+             }
+             lappend t $nextT
+         }
+     }
+     return $t
+ }
+
+ # Internal procedure that traces through the array built by ComputeLCS
+ # and finds a longest common subsequence -- specifically, the one that
+ # is lexicographically first.
+
+ proc TraceLCS { t x y } {
+     set trace {}
+     set i [expr { [llength $x] - 1 }]
+     set j [expr { [llength $y] - 1 }]
+     set k [expr { [Index $t $y $i $j] - 1 }]
+     while { $i >= 0 && $j >= 0 } {
+         set im1 [expr { $i - 1 }]
+         set jm1 [expr { $j - 1 }]
+         if { [Index $t $y $i $j] == [Index $t $y $im1 $jm1] + 1
+              && [string equal [lindex $x $i] [lindex $y $j]] } {
+             lappend trace xy [list $i $j]
+             set i $im1
+             set j $jm1
+         } elseif { [Index $t $y $im1 $j] > [Index $t $y $i $jm1] } {
+             lappend trace x $i
+             set i $im1
+         } else {
+             lappend trace y $j
+             set j $jm1
+         }
+     }
+     while { $i >= 0 } {
+         lappend trace x $i
+         incr i -1
+     }
+     while { $j >= 0 } {
+         lappend trace y $j
+         incr j -1
+     }
+     return $trace
+ }
+
+ # list::longestCommonSubsequence::compare --
+ #
+ #       Compare two lists for the longest common subsequence
+ #
+ # Arguments:
+ #       x, y - Two lists of strings to compare
+ #       matched - Callback to execute on matched elements, see below
+ #       unmatchedX - Callback to execute on unmatched elements from the
+ #                    first list, see below.
+ #       unmatchedY - Callback to execute on unmatched elements from the
+ #                    second list, see below.
+ #
+ # Results:
+ #       None.
+ #
+ # Side effects:
+ #       Whatever the callbacks do.
+ #
+ # The 'compare' procedure compares the two lists of strings, x and y.
+ # It finds a longest common subsequence between the two.  It then walks
+ # the lists in order and makes the following callbacks:
+ #
+ # For an element that is common to both lists, it appends the index in
+ # the first list, the index in the second list, and the string value of
+ # the element as three parameters to the 'matched' callback, and executes
+ # the result.
+ #
+ # For an element that is in the first list but not the second, it appends
+ # the index in the first list and the string value of the element as two
+ # parameters to the 'unmatchedX' callback and executes the result.
+ #
+ # For an element that is in the second list but not the first, it appends
+ # the index in the second list and the string value of the element as two
+ # parameters to the 'unmatchedY' callback and executes the result.
+
+ proc compare { x y
+                                                matched
+                                                unmatchedX unmatchedY } {
+     set t [ComputeLCS $x $y]
+     set trace [TraceLCS $t $x $y]
+     set i [llength $trace]
+     while { $i > 0 } {
+         set indices [lindex $trace [incr i -1]]
+         set type [lindex $trace [incr i -1]]
+         switch -exact -- $type {
+             xy {
+                 set c $matched
+                 eval lappend c $indices
+                 lappend c [lindex $x [lindex $indices 0]]
+                 uplevel 1 $c
+             }
+             x {
+                 set c $unmatchedX
+                 lappend c $indices
+                 lappend c [lindex $x $indices]
+                 uplevel 1 $c
+             }
+             y {
+                 set c $unmatchedY
+                 lappend c $indices
+                 lappend c [lindex $y $indices]
+                 uplevel 1 $c
+             }
+         }
+     }
+     return
+ }
+
+ proc umx { index value } {
+     global lastx
+     global xlines
+     append xlines "< " $value \n
+     set lastx $index
+ }
+
+ proc umy { index value } {
+     global lasty
+     global ylines
+     append ylines "> " $value \n
+     set lasty $index
+ }
+
+ proc matched { index1 index2 value } {
+     global lastx
+     global lasty
+     global xlines
+     global ylines
+     if { [info exists lastx] && [info exists lasty] } {
+     #puts "[expr { $lastx + 1 }],${index1}c[expr {$lasty + 1 }],${index2}"
+     #puts -nonewline $xlines
+     #puts "----"
+     #puts -nonewline $ylines
+     } elseif { [info exists lastx] } {
+     #puts "[expr { $lastx + 1 }],${index1}d${index2}"
+     #puts -nonewline $xlines
+     } elseif { [info exists lasty] } {
+     #puts  "${index1}a[expr {$lasty + 1 }],${index2}"
+     #puts -nonewline $ylines
+     }
+     catch { unset lastx }
+     catch { unset xlines }
+     catch { unset lasty }
+     catch { unset ylines }
+ }
+
+ # Really, we should read the first file in like this:
+ #    set f0 [open [lindex $argv 0] r]
+ #    set x [split [read $f0] \n]
+ #    close $f0
+ # But I'll just provide some sample lines:
+
+proc commonsub_test {} {
+ set x {}
+ for { set i 0 } { $i < 20 } { incr i } {
+     lappend x a r a d e d a b r a x
+ }
+
+ # The second file, too, should be read in like this:
+ #    set f1 [open [lindex $argv 1] r]
+ #    set y [split [read $f1] \n]
+ #    close $f1
+ # Once again, I'll just do some sample lines.
+
+ set y {}
+ for { set i 0 } { $i < 20 } { incr i } {
+     lappend y a b r a c a d a b r a
+ }
+
+ compare $x $y matched umx umy
+ matched [llength $x] [llength $y] {}
+}
+
+### MANDEL #####################################################################
+
+proc mandel {xres yres infx infy supx supy} {
+    set incremx [expr {(0.0+$supx-$infx)/$xres}]
+    set incremy [expr {(0.0+$supy-$infy)/$yres}]
+
+    for {set j 0} {$j < $yres} {incr j} {
+       set cim [expr {$infy+$incremy*$j}]
+       set line {}
+       for {set i 0} {$i < $xres} {incr i} {
+           set counter 0
+           set zim 0
+           set zre 0
+           set cre [expr {$infx+$incremx*$i}]
+           while {$counter < 255} {
+               set dam [expr {$zre*$zre-$zim*$zim+$cre}]
+               set zim [expr {2*$zim*$zre+$cim}]
+               set zre $dam
+               if {$zre*$zre+$zim*$zim > 4} break
+               incr counter
+           }
+           # output pixel $i $j
+       }
+    }
+}
+
+### RUN ALL ####################################################################
+
+if {[string compare [lindex $argv 0] "-batch"] == 0} {
+    set batchmode 1
+    set argv [lrange $argv 1 end]
+}
+set ver [lindex $argv 0]
+
+bench {[while] busy loop} {whilebusyloop}
+bench {[for] busy loop} {forbusyloop}
+bench {mini loops} {miniloops}
+bench {fibonacci(25)} {fibonacci 25}
+bench {heapsort} {heapsort_main}
+bench {sieve} {sieve 10}
+bench {sieve [dict]} {sieve_dict 10}
+bench {ary} {ary 100000}
+bench {ary [dict]} {ary_dict 100000}
+bench {ary [static]} {ary_static 1000000}
+bench {repeat} {use_repeat}
+bench {upvar} {upvartest}
+bench {nested loops} {nestedloops}
+bench {rotate} {rotate 100000}
+bench {dynamic code} {dyncode}
+bench {dynamic code (list)} {dyncode_list}
+bench {PI digits} {pi_digits 300}
+bench {expand} {expand}
+bench {wiki.tcl.tk/8566} {commonsub_test}
+bench {mandel} {mandel 60 60 -2 -1.5 1 1.5}
+
+if {$batchmode} {
+    if {$ver == ""} {
+        if {[catch {info patchlevel} ver]} {
+            set ver Jim[info version]
+        }
+    }
+    puts [list $ver $benchmarks]
+}
diff --git a/jim/binary.tcl b/jim/binary.tcl
new file mode 100755 (executable)
index 0000000..edc6eb1
--- /dev/null
@@ -0,0 +1,278 @@
+# Implements the 'binary scan' and 'binary format' commands.
+#
+# (c) 2010 Steve Bennett <steveb@workware.net.au>
+#
+# See LICENCE in this directory for licensing.
+
+package require pack
+package require regexp
+
+proc binary {cmd args} {
+       tailcall "binary $cmd" {*}$args
+}
+
+proc "binary format" {formatString args} {
+       set bitoffset 0
+       set result {}
+       # This RE is too unreliable...
+       foreach {conv t u n} [regexp -all -inline {([^[:space:]])(u)?([*0-9]*)} $formatString] {
+               switch -exact -- $t {
+                       a -
+                       A {
+                               set value [binary::nextarg args]
+                               set sn [string bytelength $value]
+                               if {$n ne "*"} {
+                                       if {$n eq ""} {
+                                               set n 1
+                                       }
+                                       if {$n > $sn} {
+                                               # Need to pad the string with spaces or nulls
+                                               append value [string repeat [dict get {A " " a \x00} $t] $($n - $sn)]
+                                       }
+                               } else {
+                                       set n $sn
+                               }
+                               if {$n} {
+                                       set bitoffset [pack result $value -str $(8 * $n) $bitoffset]
+                               }
+                       }
+                       x {
+                               if {$n eq "*"} {
+                                       return -code error {cannot use "*" in format string with "x"}
+                               }
+                               if {$n eq ""} {
+                                       set n 1
+                               }
+                               loop i 0 $n {
+                                       set bitoffset [pack result 0 -intbe 8 $bitoffset]
+                               }
+                       }
+                       @ {
+                               if {$n eq ""} {
+                                       return -code error {missing count for "@" field specifier}
+                               }
+                               if {$n eq "*"} {
+                                       set bitoffset $(8 * [string bytelength $result])
+                               } else {
+                                       # May need to pad it out
+                                       set max [string bytelength $result]
+                                       append result [string repeat \x00 $($n - $max)]
+                                       set bitoffset $(8 * $n)
+                               }
+                       }
+                       X {
+                               if {$n eq "*"} {
+                                       set bitoffset 0
+                               } elseif {$n eq ""} {
+                                       incr bitoffset -8
+                               } else {
+                                       incr bitoffset $($n * -8)
+                               }
+                               if {$bitoffset < 0} {
+                                       set bitoffset 0
+                               }
+                       }
+                       default {
+                               if {![info exists ::binary::scalarinfo($t)]} {
+                                       return -code error "bad field specifier \"$t\""
+                               }
+
+                               # A scalar (integer or float) type
+                               lassign $::binary::scalarinfo($t) type convtype size prefix
+                               set value [binary::nextarg args]
+
+                               if {$type in {bin hex}} {
+                                       set value [split $value {}]
+                               }
+                               set vn [llength $value]
+                               if {$n eq "*"} {
+                                       set n $vn
+                               } elseif {$n eq ""} {
+                                       set n 1
+                                       set value [list $value]
+                               } elseif {$vn < $n} {
+                                       if {$type in {bin hex}} {
+                                               # Need to pad the list with zeros
+                                               lappend value {*}[lrepeat $($n - $vn) 0]
+                                       } else {
+                                               return -code error "number of elements in list does not match count"
+                                       }
+                               } elseif {$vn > $n} {
+                                       # Need to truncate the list
+                                       set value [lrange $value 0 $n-1]
+                               }
+
+                               set convtype -$::binary::convtype($convtype)
+
+                               foreach v $value {
+                                       set bitoffset [pack result $prefix$v $convtype $size $bitoffset]
+                               }
+                               # Now pad out with zeros to the end of the current byte
+                               if {$bitoffset % 8} {
+                                       set bitoffset [pack result 0 $convtype $(8 - $bitoffset % 8) $bitoffset]
+                               }
+                       }
+               }
+       }
+       return $result
+}
+
+proc "binary scan" {value formatString {args varName}} {
+       # Pops the next arg from the front of the list and returns it.
+       # Throws an error if no more args
+       set bitoffset 0
+       set count 0
+       # This RE is too unreliable...
+       foreach {conv t u n} [regexp -all -inline {([^[:space:]])(u)?([*0-9]*)} $formatString] {
+               set rembytes $([string bytelength $value] - $bitoffset / 8)
+               switch -exact -- $t {
+                       a -
+                       A {
+                               if {$n eq "*"} {
+                                       set n $rembytes
+                               } elseif {$n eq ""} {
+                                       set n 1
+                               }
+                               if {$n > $rembytes} {
+                                       break
+                               }
+
+                               set var [binary::nextarg varName]
+
+                               set result [unpack $value -str $bitoffset $($n * 8)]
+                               incr bitoffset $([string bytelength $result] * 8)
+                               if {$t eq "A"} {
+                                       set result [string trimright $result]
+                               }
+                       }
+                       x {
+                               # Skip bytes
+                               if {$n eq "*"} {
+                                       set n $rembytes
+                               } elseif {$n eq ""} {
+                                       set n 1
+                               }
+                               if {$n > $rembytes} {
+                                       set n $rembytes
+                               }
+                               incr bitoffset $($n * 8)
+                               continue
+                       }
+                       X {
+                               # Back up bytes
+                               if {$n eq "*"} {
+                                       set bitoffset 0
+                                       continue
+                               }
+                               if {$n eq ""} {
+                                       set n 1
+                               }
+                               if {$n * 8 > $bitoffset} {
+                                       set bitoffset 0
+                                       continue
+                               }
+                               incr bitoffset -$($n * 8)
+                               continue
+                       }
+                       @ {
+                               if {$n eq ""} {
+                                       return -code error {missing count for "@" field specifier}
+                               }
+                               if {$n eq "*" || $n > $rembytes + $bitoffset / 8} {
+                                       incr bitoffset $($rembytes * 8)
+                               } elseif {$n < 0} {
+                                       set bitoffset 0
+                               } else {
+                                       set bitoffset $($n * 8)
+                               }
+                               continue
+                       }
+                       default {
+                               if {![info exists ::binary::scalarinfo($t)]} {
+                                       return -code error "bad field specifier \"$t\""
+                               }
+                               # A scalar (integer or float) type
+                               lassign $::binary::scalarinfo($t) type convtype size prefix
+                               set var [binary::nextarg varName]
+
+                               if {$n eq "*"} {
+                                       set n $($rembytes * 8 / $size)
+                               } else {
+                                       if {$n eq ""} {
+                                               set n 1
+                                       }
+                               }
+                               if {$n * $size > $rembytes * 8} {
+                                       break
+                               }
+
+                               if {$type in {hex bin}} {
+                                       set u u
+                               }
+                               set convtype -$u$::binary::convtype($convtype)
+
+                               set result {}
+                               loop i 0 $n {
+                                       set v [unpack $value $convtype $bitoffset $size]
+                                       if {$type in {bin hex}} {
+                                               append result [lindex {0 1 2 3 4 5 6 7 8 9 a b c d e f} $v]
+                                       } else {
+                                               lappend result $v
+                                       }
+                                       incr bitoffset $size
+                               }
+                               # Now skip to the end of the current byte
+                               if {$bitoffset % 8} {
+                                       incr bitoffset $(8 - ($bitoffset % 8))
+                               }
+                       }
+               }
+               uplevel 1 [list set $var $result]
+               incr count
+       }
+       return $count
+}
+
+# Pops the next arg from the front of the list and returns it.
+# Throws an error if no more args
+proc binary::nextarg {&arglist} {
+       if {[llength $arglist] == 0} {
+               return -level 2 -code error "not enough arguments for all format specifiers"
+       }
+       set arglist [lassign $arglist arg]
+       return $arg
+}
+
+set binary::scalarinfo {
+       c {int be 8}
+       s {int le 16}
+       t {int host 16}
+       S {int be 16}
+       i {int le 32}
+       I {int be 32}
+       n {int host 32}
+       w {int le 64}
+       W {int be 64}
+       m {int host 64}
+       h {hex le 4 0x}
+       H {hex be 4 0x}
+       b {bin le 1}
+       B {bin be 1}
+       r {float fle 32}
+       R {float fbe 32}
+       f {float fhost 32}
+       q {float fle 64}
+       Q {float fbe 64}
+       d {float fhost 64}
+}
+set binary::convtype {
+       be intbe
+       le intle
+       fbe floatbe
+       fle floatle
+}
+if {$::tcl_platform(byteOrder) eq "bigEndian"} {
+       array set binary::convtype {host intbe fhost floatbe}
+} else {
+       array set binary::convtype {host intle fhost floatle}
+}
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/jim/build-jim-ext.in b/jim/build-jim-ext.in
new file mode 100755 (executable)
index 0000000..087ec23
--- /dev/null
@@ -0,0 +1,255 @@
+#!/usr/bin/env jimsh
+
+# Separate command line arguments into options and source files
+set opts {}
+set sources {}
+
+proc usage {{msg {}}} {
+       puts stderr "Usage: build-jim-ext ?--notest? ?--install? ?--static? ?cc-options? ?-o modname? sources..."
+       if {$msg ne ""} {
+               puts stderr \n$msg
+       }
+       exit 1
+}
+
+proc readfile {filename {default_value ""}} {
+       set result $default_value
+       catch {
+               set f [open $filename]
+               set result [$f read -nonewline]
+               $f close
+       }
+       return $result
+}
+
+set linker "@CC@"
+set testmod 1
+set install 0
+set static 0
+set verbose 0
+set keep 0
+set includepaths {}
+set libpaths {}
+set libs {}
+for {set i 0} {$i < [llength $argv]} {incr i} {
+       set arg [lindex $argv $i]
+       switch -glob -- $arg {
+               *.c {
+                       lappend sources $arg
+               }
+               *.cpp {
+                       lappend sources $arg
+                       set linker "@CXX@"
+               }
+               --notest {
+                       set testmod 0
+               }
+               --install {
+                       set install 1
+               }
+               --static {
+                       set static 1
+               }
+               --verbose {
+                       set verbose 1
+               }
+               --keep {
+                       set keep 1
+               }
+               --help {
+                       usage "Easily builds dynamic (loadable) modules for jim"
+               }
+               -o {
+                       incr i
+                       set modname [file rootname [lindex $argv $i]]
+                       if {$modname eq ""} {
+                               usage "Option -o requires an argument"
+                       }
+               }
+               -I* {
+                       lappend includepaths $arg
+                       if {$arg eq "-I"} {
+                               lappend includepaths [lindex $argv $i]
+                       }
+               }
+               -L* {
+                       lappend libpaths $arg
+                       if {$arg eq "-L"} {
+                               lappend libpaths [lindex $argv $i]
+                       }
+               }
+               -l* {
+                       lappend libs $arg
+               }
+               -* {
+                       lappend opts $arg
+               }
+               default {
+                       usage "Unexpected '$arg'"
+               }
+       }
+}
+
+if {$sources eq ""} {
+       usage "No sources provided"
+}
+if {![info exists modname]} {
+       set modname [file rootname [file tail [lindex $sources 0]]]
+       # Remove jim- prefix if one exists
+       regsub "^jim-" $modname "" modname
+}
+
+if {$static} {
+       set target libjim-$modname.a
+} else {
+       set target $modname.so
+}
+puts "Building $target from $sources\n"
+
+# Now add the standard location after any user include paths
+lappend includepaths -I@prefix@/include
+
+set CPPFLAGS "-D_GNU_SOURCE"
+
+set ljim ""
+set shobj_cflags ""
+set shobj_ldflags ""
+if {!$static} {
+       set shobj_cflags "@SHOBJ_CFLAGS@"
+       if {"@JIM_STATICLIB@" eq "1"} {
+               puts stderr "Warning: libjim is static. Dynamic module may not work on some platforms.\n"
+               set shobj_ldflags "@SHOBJ_LDFLAGS@"
+       } else {
+               # If shared, link against the shared libjim to resolve symbols
+               set ljim -ljim
+               set shobj_ldflags "@SHOBJ_LDFLAGS_R@"
+       }
+}
+
+set objs {}
+foreach source $sources {
+       set obj [file rootname [file tail $source]].o
+       if {[string match *.c $source]} {
+               set compiler "@CC@"
+       } else {
+               set compiler "@CXX@"
+       }
+       set compile "$compiler @CFLAGS@ $CPPFLAGS $shobj_cflags $includepaths $opts -c -o $obj $source"
+       puts "Compile: $obj"
+       lappend objs $obj
+       flush stdout
+       set rc [catch {
+               if {$verbose} {
+                       puts $compile
+               }
+               exec 2>jimerr.out {*}$compile
+       } msg]
+
+       set errmsg [readfile jimerr.out]
+       file delete jimerr.out
+
+       if {$rc} {
+               if {!$verbose} {
+                       puts stderr $compile
+               }
+               puts stderr $msg
+               if {$errmsg ne ""} {
+                       puts stderr $errmsg
+               }
+               file delete {*}$objs
+               exit 1
+       } else {
+               if {$errmsg ne ""} {
+                       puts $errmsg
+               }
+       }
+}
+
+if {$static} {
+       set ar "@AR@ cq $target $objs"
+       set ranlib "@RANLIB@ $target"
+
+       puts "Ar:      $target"
+       set rc [catch {
+               file delete $target
+               exec {*}$ar
+               exec {*}$ranlib
+               if {$verbose} {
+                       puts stderr $ar
+               }
+       } msg]
+
+       file delete {*}$objs
+
+       if {$rc} {
+               puts stderr $ar
+               puts stderr $ranlib
+               puts stderr $msg
+               file delete $target
+               exit 1
+       }
+} else {
+       # Add the standard location after any user lib paths
+       lappend libpaths -L@prefix@/lib
+
+       set link "$linker @CFLAGS@ @LDFLAGS@ $shobj_ldflags $libpaths $opts -o $target $objs $ljim @LIBS@ $libs"
+
+       puts "Link:    $target"
+       set rc [catch {
+               if {$verbose} {
+                       puts stderr $link
+               }
+               exec 2>jimerr.out {*}$link
+       } msg]
+
+       set errmsg [readfile jimerr.out]
+       file delete jimerr.out
+
+       if {!$keep} {
+               file delete {*}$objs
+       }
+
+       if {$rc} {
+               file delete $target
+               puts stderr $link
+               puts stderr $msg
+               if {$errmsg ne ""} {
+                       puts stderr $errmsg
+               }
+               exit 1
+       }
+       if {$errmsg ne ""} {
+               puts $errmsg
+       }
+
+       if {$testmod} {
+               # Now, is testing even possible?
+               # We must be running a compatible jimsh with the load command at least
+               set testmod 0
+               set rc [catch {
+                       # This will avoid attempting on Tcl and on jimsh without load
+                       # How to tell if we are cross compiling?
+                       if {[info version] > 0.73 && [exists -command load]} {
+                               set testmod 1
+                       }
+               } msg]
+       }
+
+       set rc [catch {
+               if {$testmod} {
+                       puts "Test:    load $target"
+                       load ./$target
+               }
+               if {$install} {
+                       set dest [env DESTDIR ""]@prefix@/lib/jim
+                       puts "Install: $target => $dest"
+                       file mkdir $dest
+                       file copy $target $dest/$target
+               }
+               puts "\nSuccess!"
+       } msg]
+       if {$rc} {
+               puts stderr $msg
+               exit 1
+       }
+}
index 1c5586f..8367bd8 100755 (executable)
@@ -1,3 +1,3 @@
 #!/bin/sh
 dir="`dirname "$0"`/autosetup"
-WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
+WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index cd94d8d..6b1ad39
-# Implements a Tcl-compatible glob command based on readdir
+# Implements a mostly Tcl-compatible glob command based on readdir
 #
 # (c) 2008 Steve Bennett <steveb@workware.net.au>
+# (c) 2012 Alexander Shpilkin <ashpilkin@gmail.com>
 #
 # See LICENCE in this directory for licensing.
 
 package require readdir
 
-# Implements the Tcl glob command
-#
-# Usage: glob ?-nocomplain? pattern ...
-#
-# Patterns use 'string match' (glob) pattern matching for each
-# directory level, plus support for braced alternations.
-#
-# e.g. glob "te[a-e]*/*.{c,tcl}"
-#
-# Note: files starting with . will only be returned if matching component
-#       of the pattern starts with .
-proc glob {args} {
-
-       # If $dir is a directory, return a list of all entries
-       # it contains which match $pattern
-       #
-       local proc glob.readdir_pattern {dir pattern} {
-               set result {}
-
-               # readdir doesn't return . or .., so simulate it here
-               if {$pattern in {. ..}} {
-                       return $pattern
+# Return a list of all entries in $dir that match the pattern.
+proc glob.globdir {dir pattern} {
+       set result {}
+       set files [readdir $dir]
+       lappend files . ..
+
+       foreach name $files {
+               if {[string match $pattern $name]} {
+                       # Starting dots match only explicitly
+                       if {[string index $name 0] eq "." && [string index $pattern 0] ne "."} {
+                               continue
+                       }
+                       lappend result $name
                }
+       }
 
-               # If the pattern isn't actually a pattern...
-               if {[string match {*[*?]*} $pattern]} {
-                       # Use -nocomplain here to return nothing if $dir is not a directory
-                       set files [readdir -nocomplain $dir]
-               } elseif {[file isdir $dir] && [file exists $dir/$pattern]} {
-                       set files [list $pattern]
-               } else {
-                       set files ""
-               }
+       return $result
+}
 
-               foreach name $files {
-                       if {[string match $pattern $name]} {
-                               # Only include entries starting with . if the pattern starts with .
-                               if {[string index $name 0] eq "." && [string index $pattern 0] ne "."} {
-                                       continue
+# Return the list of patterns resulting from expanding any braced
+# alternatives inside the given pattern, prepending the unprocessed
+# part of the pattern. Does _not_ handle escaped braces or commas.
+proc glob.explode {pattern} {
+       set oldexp {}
+       set newexp {""}
+
+       while 1 {
+               set oldexp $newexp
+               set newexp {}
+               set ob [string first \{ $pattern]
+               set cb [string first \} $pattern]
+
+               if {$ob < $cb && $ob != -1} {
+                       set mid [string range $pattern 0 $ob-1]
+                       set subexp [lassign [glob.explode [string range $pattern $ob+1 end]] pattern]
+                       if {$pattern eq ""} {
+                               error "unmatched open brace in glob pattern"
+                       }
+                       set pattern [string range $pattern 1 end]
+
+                       foreach subs $subexp {
+                               foreach sub [split $subs ,] {
+                                       foreach old $oldexp {
+                                               lappend newexp $old$mid$sub
+                                       }
                                }
-                               lappend result $name
                        }
+               } elseif {$cb != -1} {
+                       set suf  [string range $pattern 0 $cb-1]
+                       set rest [string range $pattern $cb end]
+                       break
+               } else {
+                       set suf  $pattern
+                       set rest ""
+                       break
                }
+       }
 
-               return $result
+       foreach old $oldexp {
+               lappend newexp $old$suf
        }
+       linsert $newexp 0 $rest
+}
 
-       # If the pattern contains a braced expression, return a list of
-       # patterns with the braces expanded. {c,b}* => c* b*
-       # Otherwise just return the pattern
-       # Note: Only supports one braced expression. i.e. not {a,b}*{c,d}*
-       proc glob.expandbraces {pattern} {
-               # Avoid regexp for dependency reasons.
-               # XXX: Doesn't handle backslashed braces
-               if {[set fb [string first "\{" $pattern]] < 0} {
-                       return $pattern
+# Core glob implementation. Returns a list of files/directories inside
+# base matching pattern, in {realname name} pairs.
+proc glob.glob {base pattern} {
+       set dir [file dirname $pattern]
+       if {$pattern eq $dir || $pattern eq ""} {
+               return [list [file join $base $dir] $pattern]
+       } elseif {$pattern eq [file tail $pattern]} {
+               set dir ""
+       }
+
+       # Recursively expand the parent directory
+       set dirlist [glob.glob $base $dir]
+       set pattern [file tail $pattern]
+
+       # Collect the files/directories
+       set result {}
+       foreach {realdir dir} $dirlist {
+               if {![file isdir $realdir]} {
+                       continue
                }
-               if {[set nb [string first "\}" $pattern $fb]] < 0} {
-                       return $pattern
+               if {[string index $dir end] ne "/" && $dir ne ""} {
+                       append dir /
                }
-               set before [string range $pattern 0 $fb-1]
-               set braced [string range $pattern $fb+1 $nb-1]
-               set after [string range $pattern $nb+1 end]
-
-               lmap part [split $braced ,] {
-                       set pat $before$part$after
+               foreach name [glob.globdir $realdir $pattern] {
+                       lappend result [file join $realdir $name] $dir$name
                }
        }
+       return $result
+}
 
-       # Core glob implementation. Returns a list of files/directories matching the pattern
-       proc glob.glob {pattern} {
-               set dir [file dirname $pattern]
-               if {$dir eq $pattern} {
-                       # At the top level
-                       return [list $dir]
+# Implements the Tcl glob command
+#
+# Usage: glob ?-nocomplain? ?-directory dir? ?--? pattern ...
+#
+# Patterns use 'string match' (glob) pattern matching for each
+# directory level, plus support for braced alternations.
+#
+# e.g. glob {te[a-e]*/*.{c,tcl}}
+#
+# Note: files starting with . will only be returned if matching component
+#       of the pattern starts with .
+proc glob {args} {
+       set nocomplain 0
+       set base ""
+
+       set n 0
+       foreach arg $args {
+               if {[info exists param]} {
+                       set $param $arg
+                       unset param
+                       incr n
+                       continue
                }
+               switch -glob -- $arg {
+                       -d* {
+                               set switch $arg
+                               set param base
+                       }
+                       -n* {
+                               set nocomplain 1
+                       }
+                       -t* {
+                               # Ignored for Tcl compatibility
+                       }
 
-               # Recursively expand the parent directory
-               set dirlist [glob.glob $dir]
-               set pattern [file tail $pattern]
-
-               # Now collect the fiels/directories
-               set result {}
-               foreach dir $dirlist {
-                       set globdir $dir
-                       if {[string match "*/" $dir]} {
-                               set sep ""
-                       } elseif {$dir eq "."} {
-                               set globdir ""
-                               set sep ""
-                       } else {
-                               set sep /
+                       -* {
+                               return -code error "bad option \"$switch\": must be -directory, -nocomplain, -tails, or --"
                        }
-                       foreach pat [glob.expandbraces $pattern] {
-                               foreach name [glob.readdir_pattern $dir $pat] {
-                                       lappend result $globdir$sep$name
-                               }
+                       -- {
+                               incr n
+                               break
+                       }
+                       *  {
+                               break
                        }
                }
-               return $result
+               incr n
        }
-
-       # Start of main glob
-       set nocomplain 0
-
-       if {[lindex $args 0] eq "-nocomplain"} {
-               set nocomplain 1
-               set args [lrange $args 1 end]
+       if {[info exists param]} {
+               return -code error "missing argument to \"$switch\""
+       }
+       if {[llength $args] <= $n} {
+               return -code error "wrong # args: should be \"glob ?options? pattern ?pattern ...?\""
        }
 
+       set args [lrange $args $n end]
+
        set result {}
        foreach pattern $args {
-               lappend result {*}[glob.glob $pattern]
+               set pattern [string map {
+                       \\\\ \x01 \\\{ \x02 \\\} \x03 \\, \x04
+               } $pattern]
+               set patexps [lassign [glob.explode $pattern] rest]
+               if {$rest ne ""} {
+                       return -code error "unmatched close brace in glob pattern"
+               }
+               foreach patexp $patexps {
+                       set patexp [string map {
+                               \x01 \\\\ \x02 \{ \x03 \} \x04 ,
+                       } $patexp]
+                       foreach {realname name} [glob.glob $base $patexp] {
+                               lappend result $name
+                       }
+               }
        }
 
-       if {$nocomplain == 0 && [llength $result] == 0} {
+       if {!$nocomplain && [llength $result] == 0} {
                return -code error "no files matched glob patterns"
        }
 
old mode 100644 (file)
new mode 100755 (executable)
index 710a47d..70fc1e3 100644 (file)
@@ -1,4 +1,3 @@
-
 /* Jim - A small embeddable Tcl interpreter
  *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  * official policies, either expressed or implied, of the Jim Tcl Project.
  **/
 
-#include <unistd.h>
+#include "jimautoconf.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#include <sys/stat.h>
+#endif
 
 #include "jim.h"
-#include "jimautoconf.h"
 
 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H)
 #include <sys/socket.h>
 #define AIO_CMD_LEN 32      /* e.g. aio.handleXXXXXX */
 #define AIO_BUF_LEN 256     /* Can keep this small and rely on stdio buffering */
 
+#ifndef HAVE_FTELLO
+    #define ftello ftell
+#endif
+#ifndef HAVE_FSEEKO
+    #define fseeko fseek
+#endif
+
 #define AIO_KEEPOPEN 1
 
 #if defined(JIM_IPV6)
@@ -102,11 +112,8 @@ typedef struct AioFile
     FILE *fp;
     Jim_Obj *filename;
     int type;
-    int OpenFlags;              /* AIO_KEEPOPEN? keep FILE* */
+    int openFlags;              /* AIO_KEEPOPEN? keep FILE* */
     int fd;
-#ifdef O_NDELAY
-    int flags;
-#endif
     Jim_Obj *rEvent;
     Jim_Obj *wEvent;
     Jim_Obj *eEvent;
@@ -279,22 +286,40 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
 
     Jim_DecrRefCount(interp, af->filename);
 
-    if (!(af->OpenFlags & AIO_KEEPOPEN)) {
+#ifdef jim_ext_eventloop
+    /* remove all existing EventHandlers */
+    Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
+#endif
+
+    if (!(af->openFlags & AIO_KEEPOPEN)) {
         fclose(af->fp);
     }
-#ifdef jim_ext_eventloop
-    /* remove existing EventHandlers */
-    if (af->rEvent) {
-        Jim_DeleteFileHandler(interp, af->fp);
+
+    Jim_Free(af);
+}
+
+static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
+{
+    if (!ferror(af->fp)) {
+        return JIM_OK;
     }
-    if (af->wEvent) {
-        Jim_DeleteFileHandler(interp, af->fp);
+    clearerr(af->fp);
+    /* EAGAIN and similar are not error conditions. Just treat them like eof */
+    if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
+        return JIM_OK;
     }
-    if (af->eEvent) {
-        Jim_DeleteFileHandler(interp, af->fp);
+#ifdef ECONNRESET
+    if (errno == ECONNRESET) {
+        return JIM_OK;
     }
 #endif
-    Jim_Free(af);
+#ifdef ECONNABORTED
+    if (errno != ECONNABORTED) {
+        return JIM_OK;
+    }
+#endif
+    JimAioSetError(interp, af->filename);
+    return JIM_ERR;
 }
 
 static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -303,7 +328,7 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     char buf[AIO_BUF_LEN];
     Jim_Obj *objPtr;
     int nonewline = 0;
-    int neededLen = -1;         /* -1 is "read as much as possible" */
+    jim_wide neededLen = -1;         /* -1 is "read as much as possible" */
 
     if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
         nonewline = 1;
@@ -311,15 +336,12 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         argc--;
     }
     if (argc == 1) {
-        jim_wide wideValue;
-
-        if (Jim_GetWide(interp, argv[0], &wideValue) != JIM_OK)
+        if (Jim_GetWide(interp, argv[0], &neededLen) != JIM_OK)
             return JIM_ERR;
-        if (wideValue < 0) {
+        if (neededLen < 0) {
             Jim_SetResultString(interp, "invalid parameter: negative len", -1);
             return JIM_ERR;
         }
-        neededLen = (int)wideValue;
     }
     else if (argc) {
         return -1;
@@ -346,15 +368,9 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
             break;
     }
     /* Check for error conditions */
-    if (ferror(af->fp)) {
-        clearerr(af->fp);
-        /* eof and EAGAIN are not error conditions */
-        if (!feof(af->fp) && errno != EAGAIN) {
-            /* I/O error */
-            Jim_FreeNewObj(interp, objPtr);
-            JimAioSetError(interp, af->filename);
-            return JIM_ERR;
-        }
+    if (JimCheckStreamError(interp, af)) {
+        Jim_FreeNewObj(interp, objPtr);
+        return JIM_ERR;
     }
     if (nonewline) {
         int len;
@@ -372,8 +388,8 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     AioFile *af = Jim_CmdPrivData(interp);
-    long count = 0;
-    long maxlen = LONG_MAX;
+    jim_wide count = 0;
+    jim_wide maxlen = JIM_WIDE_MAX;
     FILE *outfh = Jim_AioFilehandle(interp, argv[0]);
 
     if (outfh == NULL) {
@@ -381,7 +397,7 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     }
 
     if (argc == 2) {
-        if (Jim_GetLong(interp, argv[1], &maxlen) != JIM_OK) {
+        if (Jim_GetWide(interp, argv[1], &maxlen) != JIM_OK) {
             return JIM_ERR;
         }
     }
@@ -442,11 +458,9 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
             break;
         }
     }
-    if (ferror(af->fp) && errno != EAGAIN && errno != EINTR) {
+    if (JimCheckStreamError(interp, af)) {
         /* I/O error */
         Jim_FreeNewObj(interp, objPtr);
-        JimAioSetError(interp, af->filename);
-        clearerr(af->fp);
         return JIM_ERR;
     }
 
@@ -497,6 +511,18 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     return JIM_ERR;
 }
 
+static int aio_cmd_isatty(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+#ifdef HAVE_ISATTY
+    AioFile *af = Jim_CmdPrivData(interp);
+    Jim_SetResultInt(interp, isatty(fileno(af->fp)));
+#else
+    Jim_SetResultInt(interp, 0);
+#endif
+
+    return JIM_OK;
+}
+
 #if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP)
 static int aio_cmd_recvfrom(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -535,11 +561,15 @@ static int aio_cmd_recvfrom(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         }
         else
 #endif
-        {
+        if (sa.sa.sa_family == PF_INET) {
             /* Allow 7 for :65535\0 */
             inet_ntop(sa.sa.sa_family, &sa.sin.sin_addr, addrbuf, sizeof(addrbuf) - 7);
             snprintf(addrbuf + strlen(addrbuf), 7, ":%d", ntohs(sa.sin.sin_port));
         }
+        else {
+            /* recvfrom still works on unix domain sockets, etc */
+            addrbuf[0] = 0;
+        }
 
         if (Jim_SetVariable(interp, argv[1], Jim_NewStringObj(interp, addrbuf, -1)) != JIM_OK) {
             return JIM_ERR;
@@ -637,15 +667,34 @@ static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
 static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    Jim_DeleteCommand(interp, Jim_String(argv[0]));
-    return JIM_OK;
+    if (argc == 3) {
+#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN)
+        static const char * const options[] = { "r", "w", NULL };
+        enum { OPT_R, OPT_W, };
+        int option;
+        AioFile *af = Jim_CmdPrivData(interp);
+
+        if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
+            return JIM_ERR;
+        }
+        if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) {
+            return JIM_OK;
+        }
+        JimAioSetError(interp, NULL);
+#else
+        Jim_SetResultString(interp, "async close not supported", -1);
+#endif
+        return JIM_ERR;
+    }
+
+    return Jim_DeleteCommand(interp, Jim_String(argv[0]));
 }
 
 static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     AioFile *af = Jim_CmdPrivData(interp);
     int orig = SEEK_SET;
-    long offset;
+    jim_wide offset;
 
     if (argc == 2) {
         if (Jim_CompareStringImmediate(interp, argv[1], "start"))
@@ -658,10 +707,10 @@ static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
             return -1;
         }
     }
-    if (Jim_GetLong(interp, argv[0], &offset) != JIM_OK) {
+    if (Jim_GetWide(interp, argv[0], &offset) != JIM_OK) {
         return JIM_ERR;
     }
-    if (fseek(af->fp, offset, orig) == -1) {
+    if (fseeko(af->fp, offset, orig) == -1) {
         JimAioSetError(interp, af->filename);
         return JIM_ERR;
     }
@@ -672,7 +721,7 @@ static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     AioFile *af = Jim_CmdPrivData(interp);
 
-    Jim_SetResultInt(interp, ftell(af->fp));
+    Jim_SetResultInt(interp, ftello(af->fp));
     return JIM_OK;
 }
 
@@ -689,7 +738,7 @@ static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     AioFile *af = Jim_CmdPrivData(interp);
 
-    int fmode = af->flags;
+    int fmode = fcntl(af->fd, F_GETFL);
 
     if (argc) {
         long nb;
@@ -703,8 +752,7 @@ static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         else {
             fmode &= ~O_NDELAY;
         }
-        fcntl(af->fd, F_SETFL, fmode);
-        af->flags = fmode;
+        (void)fcntl(af->fd, F_SETFL, fmode);
     }
     Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
     return JIM_OK;
@@ -749,23 +797,22 @@ static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 #ifdef jim_ext_eventloop
 static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
 {
-    Jim_Obj *objPtr = clientData;
+    Jim_Obj **objPtrPtr = clientData;
 
-    Jim_DecrRefCount(interp, objPtr);
+    Jim_DecrRefCount(interp, *objPtrPtr);
+    *objPtrPtr = NULL;
 }
 
 static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
 {
-    Jim_Obj *objPtr = clientData;
+    Jim_Obj **objPtrPtr = clientData;
 
-    return Jim_EvalObjBackground(interp, objPtr);
+    return Jim_EvalObjBackground(interp, *objPtrPtr);
 }
 
 static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
     int argc, Jim_Obj * const *argv)
 {
-    int scriptlen = 0;
-
     if (argc == 0) {
         /* Return current script */
         if (*scriptHandlerObj) {
@@ -776,13 +823,11 @@ static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Ob
 
     if (*scriptHandlerObj) {
         /* Delete old handler */
-        Jim_DeleteFileHandler(interp, af->fp);
-        *scriptHandlerObj = NULL;
+        Jim_DeleteFileHandler(interp, af->fp, mask);
     }
 
     /* Now possibly add the new script(s) */
-    Jim_GetString(argv[0], &scriptlen);
-    if (scriptlen == 0) {
+    if (Jim_Length(argv[0]) == 0) {
         /* Empty script, so done */
         return JIM_OK;
     }
@@ -792,7 +837,7 @@ static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Ob
     *scriptHandlerObj = argv[0];
 
     Jim_CreateFileHandler(interp, af->fp, mask,
-        JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer);
+        JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer);
 
     return JIM_OK;
 }
@@ -815,134 +860,159 @@ static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *arg
 {
     AioFile *af = Jim_CmdPrivData(interp);
 
-    return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
+    return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv);
 }
 #endif
 
 static const jim_subcmd_type aio_command_table[] = {
-    {   .cmd = "read",
-        .args = "?-nonewline? ?len?",
-        .function = aio_cmd_read,
-        .minargs = 0,
-        .maxargs = 2,
-        .description = "Read and return bytes from the stream. To eof if no len."
+    {   "read",
+        "?-nonewline? ?len?",
+        aio_cmd_read,
+        0,
+        2,
+        /* Description: Read and return bytes from the stream. To eof if no len. */
+    },
+    {   "copyto",
+        "handle ?size?",
+        aio_cmd_copy,
+        1,
+        2,
+        /* Description: Copy up to 'size' bytes to the given filehandle, or to eof if no size. */
     },
-    {   .cmd = "copyto",
-        .args = "handle ?size?",
-        .function = aio_cmd_copy,
-        .minargs = 1,
-        .maxargs = 2,
-        .description = "Copy up to 'size' bytes to the given filehandle, or to eof if no size."
+    {   "gets",
+        "?var?",
+        aio_cmd_gets,
+        0,
+        1,
+        /* Description: Read one line and return it or store it in the var */
     },
-    {   .cmd = "gets",
-        .args = "?var?",
-        .function = aio_cmd_gets,
-        .minargs = 0,
-        .maxargs = 1,
-        .description = "Read one line and return it or store it in the var"
+    {   "puts",
+        "?-nonewline? str",
+        aio_cmd_puts,
+        1,
+        2,
+        /* Description: Write the string, with newline unless -nonewline */
     },
-    {   .cmd = "puts",
-        .args = "?-nonewline? str",
-        .function = aio_cmd_puts,
-        .minargs = 1,
-        .maxargs = 2,
-        .description = "Write the string, with newline unless -nonewline"
+    {   "isatty",
+        NULL,
+        aio_cmd_isatty,
+        0,
+        0,
+        /* Description: Is the file descriptor a tty? */
     },
 #if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP)
-    {   .cmd = "recvfrom",
-        .args = "len ?addrvar?",
-        .function = aio_cmd_recvfrom,
-        .minargs = 1,
-        .maxargs = 2,
-        .description = "Receive up to 'len' bytes on the socket. Sets 'addrvar' with receive address, if set"
+    {   "recvfrom",
+        "len ?addrvar?",
+        aio_cmd_recvfrom,
+        1,
+        2,
+        /* Description: Receive up to 'len' bytes on the socket. Sets 'addrvar' with receive address, if set */
     },
-    {   .cmd = "sendto",
-        .args = "str address",
-        .function = aio_cmd_sendto,
-        .minargs = 2,
-        .maxargs = 2,
-        .description = "Send 'str' to the given address (dgram only)"
+    {   "sendto",
+        "str address",
+        aio_cmd_sendto,
+        2,
+        2,
+        /* Description: Send 'str' to the given address (dgram only) */
     },
-    {   .cmd = "accept",
-        .function = aio_cmd_accept,
-        .description = "Server socket only: Accept a connection and return stream"
+    {   "accept",
+        NULL,
+        aio_cmd_accept,
+        0,
+        0,
+        /* Description: Server socket only: Accept a connection and return stream */
     },
-    {   .cmd = "listen",
-        .args = "backlog",
-        .function = aio_cmd_listen,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Set the listen backlog for server socket"
+    {   "listen",
+        "backlog",
+        aio_cmd_listen,
+        1,
+        1,
+        /* Description: Set the listen backlog for server socket */
     },
 #endif /* JIM_BOOTSTRAP */
-    {   .cmd = "flush",
-        .function = aio_cmd_flush,
-        .description = "Flush the stream"
+    {   "flush",
+        NULL,
+        aio_cmd_flush,
+        0,
+        0,
+        /* Description: Flush the stream */
     },
-    {   .cmd = "eof",
-        .function = aio_cmd_eof,
-        .description = "Returns 1 if stream is at eof"
+    {   "eof",
+        NULL,
+        aio_cmd_eof,
+        0,
+        0,
+        /* Description: Returns 1 if stream is at eof */
     },
-    {   .cmd = "close",
-        .flags = JIM_MODFLAG_FULLARGV,
-        .function = aio_cmd_close,
-        .description = "Closes the stream"
+    {   "close",
+        "?r(ead)|w(rite)?",
+        aio_cmd_close,
+        0,
+        1,
+        JIM_MODFLAG_FULLARGV,
+        /* Description: Closes the stream. */
     },
-    {   .cmd = "seek",
-        .args = "offset ?start|current|end",
-        .function = aio_cmd_seek,
-        .minargs = 1,
-        .maxargs = 2,
-        .description = "Seeks in the stream (default 'current')"
+    {   "seek",
+        "offset ?start|current|end",
+        aio_cmd_seek,
+        1,
+        2,
+        /* Description: Seeks in the stream (default 'current') */
     },
-    {   .cmd = "tell",
-        .function = aio_cmd_tell,
-        .description = "Returns the current seek position"
+    {   "tell",
+        NULL,
+        aio_cmd_tell,
+        0,
+        0,
+        /* Description: Returns the current seek position */
     },
-    {   .cmd = "filename",
-        .function = aio_cmd_filename,
-        .description = "Returns the original filename"
+    {   "filename",
+        NULL,
+        aio_cmd_filename,
+        0,
+        0,
+        /* Description: Returns the original filename */
     },
 #ifdef O_NDELAY
-    {   .cmd = "ndelay",
-        .args = "?0|1?",
-        .function = aio_cmd_ndelay,
-        .minargs = 0,
-        .maxargs = 1,
-        .description = "Set O_NDELAY (if arg). Returns current/new setting."
+    {   "ndelay",
+        "?0|1?",
+        aio_cmd_ndelay,
+        0,
+        1,
+        /* Description: Set O_NDELAY (if arg). Returns current/new setting. */
     },
 #endif
-    {   .cmd = "buffering",
-        .args = "none|line|full",
-        .function = aio_cmd_buffering,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Sets buffering"
+    {   "buffering",
+        "none|line|full",
+        aio_cmd_buffering,
+        1,
+        1,
+        /* Description: Sets buffering */
     },
 #ifdef jim_ext_eventloop
-    {   .cmd = "readable",
-        .args = "?readable-script?",
-        .minargs = 0,
-        .maxargs = 1,
-        .function = aio_cmd_readable,
-        .description = "Returns script, or invoke readable-script when readable, {} to remove",
+    {   "readable",
+        "?readable-script?",
+        aio_cmd_readable,
+        0,
+        1,
+        /* Description: Returns script, or invoke readable-script when readable, {} to remove */
     },
-    {   .cmd = "writable",
-        .args = "?writable-script?",
-        .minargs = 0,
-        .maxargs = 1,
-        .function = aio_cmd_writable,
-        .description = "Returns script, or invoke writable-script when writable, {} to remove",
+    {   "writable",
+        "?writable-script?",
+        aio_cmd_writable,
+        0,
+        1,
+        /* Description: Returns script, or invoke writable-script when writable, {} to remove */
     },
-    {   .cmd = "onexception",
-        .args = "?exception-script?",
-        .minargs = 0,
-        .maxargs = 1,
-        .function = aio_cmd_onexception,
-        .description = "Returns script, or invoke exception-script when oob data, {} to remove",
+    {   "onexception",
+        "?exception-script?",
+        aio_cmd_onexception,
+        0,
+        1,
+        /* Description: Returns script, or invoke exception-script when oob data, {} to remove */
     },
 #endif
-    { 0 }
+    { NULL }
 };
 
 static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -953,8 +1023,6 @@ static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 static int JimAioOpenCommand(Jim_Interp *interp, int argc,
         Jim_Obj *const *argv)
 {
-    FILE *fp;
-    const char *hdlfmt;
     const char *mode;
 
     if (argc != 2 && argc != 3) {
@@ -963,45 +1031,31 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc,
     }
 
     mode = (argc == 3) ? Jim_String(argv[2]) : "r";
-    hdlfmt = Jim_String(argv[1]);
-    if (Jim_CompareStringImmediate(interp, argv[1], "stdin")) {
-        fp = stdin;
-    }
-    else if (Jim_CompareStringImmediate(interp, argv[1], "stdout")) {
-        fp = stdout;
-    }
-    else if (Jim_CompareStringImmediate(interp, argv[1], "stderr")) {
-        fp = stderr;
-    }
-    else {
-        const char *filename = Jim_String(argv[1]);
-
 
 #ifdef jim_ext_tclcompat
+    {
+        const char *filename = Jim_String(argv[1]);
+
         /* If the filename starts with '|', use popen instead */
         if (*filename == '|') {
             Jim_Obj *evalObj[3];
 
-            evalObj[0] = Jim_NewStringObj(interp, "popen", -1);
+            evalObj[0] = Jim_NewStringObj(interp, "::popen", -1);
             evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1);
             evalObj[2] = Jim_NewStringObj(interp, mode, -1);
 
             return Jim_EvalObjVector(interp, 3, evalObj);
         }
-#endif
-        hdlfmt = "aio.handle%ld";
-        fp = NULL;
     }
-
-    /* Create the file command */
-    return JimMakeChannel(interp, fp, -1, argv[1], hdlfmt, 0, mode);
+#endif
+    return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
 }
 
 /**
  * Creates a channel for fh/fd/filename.
  *
- * If fh is not NULL, uses that as the channel (and set AIO_KEEPOPEN).
- * Otherwise, if fd is >= 0, uses that as the chanel.
+ * If fh is not NULL, uses that as the channel (and sets AIO_KEEPOPEN).
+ * Otherwise, if fd is >= 0, uses that as the channel.
  * Otherwise opens 'filename' with mode 'mode'.
  *
  * hdlfmt is a sprintf format for the filehandle. Anything with %ld at the end will do.
@@ -1014,27 +1068,34 @@ static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filenam
 {
     AioFile *af;
     char buf[AIO_CMD_LEN];
-    int OpenFlags = 0;
+    int openFlags = 0;
+
+    if (fh) {
+        filename = Jim_NewStringObj(interp, hdlfmt, -1);
+        openFlags = AIO_KEEPOPEN;
+    }
 
     Jim_IncrRefCount(filename);
 
     if (fh == NULL) {
-        if (fd < 0) {
-            fh = fopen(Jim_String(filename), mode);
-        }
-        else {
+#if !defined(JIM_ANSIC)
+        if (fd >= 0) {
             fh = fdopen(fd, mode);
         }
-    }
-    else {
-        OpenFlags = AIO_KEEPOPEN;
-    }
+        else
+#endif
+            fh = fopen(Jim_String(filename), mode);
 
-    if (fh == NULL) {
-        JimAioSetError(interp, filename);
-        close(fd);
-        Jim_DecrRefCount(interp, filename);
-        return JIM_ERR;
+        if (fh == NULL) {
+            JimAioSetError(interp, filename);
+#if !defined(JIM_ANSIC)
+            if (fd >= 0) {
+                close(fd);
+            }
+#endif
+            Jim_DecrRefCount(interp, filename);
+            return JIM_ERR;
+        }
     }
 
     /* Create the file command */
@@ -1044,23 +1105,44 @@ static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filenam
     af->fd = fileno(fh);
     af->filename = filename;
 #ifdef FD_CLOEXEC
-    if ((OpenFlags & AIO_KEEPOPEN) == 0) {
-        fcntl(af->fd, F_SETFD, FD_CLOEXEC);
-        af->OpenFlags = OpenFlags;
+    if ((openFlags & AIO_KEEPOPEN) == 0) {
+        (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC);
     }
 #endif
-#ifdef O_NDELAY
-    af->flags = fcntl(af->fd, F_GETFL);
-#endif
+    af->openFlags = openFlags;
     af->addr_family = family;
     snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
     Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
 
-    Jim_SetResultString(interp, buf, -1);
+    /* Note that the command must use the global namespace, even if
+     * the current namespace is something different
+     */
+    Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
 
     return JIM_OK;
 }
 
+static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
+    const char *hdlfmt, int family, const char *mode[2])
+{
+    if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) {
+        Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
+        Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
+
+        if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) {
+            Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
+            Jim_SetResult(interp, objPtr);
+            return JIM_OK;
+        }
+    }
+
+    /* Can only be here if fdopen() failed */
+    close(p[0]);
+    close(p[1]);
+    JimAioSetError(interp, NULL);
+    return JIM_ERR;
+}
+
 #if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP)
 
 static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -1074,6 +1156,7 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         "stream",
         "stream.server",
         "pipe",
+        "pair",
         NULL
     };
     enum
@@ -1085,10 +1168,7 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         SOCK_STREAM_CLIENT,
         SOCK_STREAM_SERVER,
         SOCK_STREAM_PIPE,
-        SOCK_DGRAM6_CLIENT,
-        SOCK_DGRAM6_SERVER,
-        SOCK_STREAM6_CLIENT,
-        SOCK_STREAM6_SERVER,
+        SOCK_STREAM_SOCKETPAIR,
     };
     int socktype;
     int sock;
@@ -1284,38 +1364,45 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
             }
 #endif
 
-#ifdef HAVE_PIPE
-        case SOCK_STREAM_PIPE:
+#if defined(HAVE_SOCKETPAIR) && defined(HAVE_SYS_UN_H)
+        case SOCK_STREAM_SOCKETPAIR:
             {
                 int p[2];
+                static const char *mode[2] = { "r+", "r+" };
 
                 if (argc != 2 || ipv6) {
                     goto wrongargs;
                 }
 
-                if (pipe(p) < 0) {
+                if (socketpair(PF_UNIX, SOCK_STREAM, 0, p) < 0) {
                     JimAioSetError(interp, NULL);
                     return JIM_ERR;
                 }
+                return JimMakeChannelPair(interp, p, argv[1], "aio.sockpair%ld", PF_UNIX, mode);
+            }
+            break;
+#endif
 
-                if (JimMakeChannel(interp, NULL, p[0], argv[1], "aio.pipe%ld", 0, "r") == JIM_OK) {
-                    Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
-                    Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
+#if defined(HAVE_PIPE)
+        case SOCK_STREAM_PIPE:
+            {
+                int p[2];
+                static const char *mode[2] = { "r", "w" };
 
-                    if (JimMakeChannel(interp, NULL, p[1], argv[1], "aio.pipe%ld", 0, "w") == JIM_OK) {
-                        Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
-                        Jim_SetResult(interp, objPtr);
-                        return JIM_OK;
-                    }
+                if (argc != 2 || ipv6) {
+                    goto wrongargs;
                 }
-                /* Can only be here if fdopen() failed */
-                close(p[0]);
-                close(p[1]);
-                JimAioSetError(interp, NULL);
-                return JIM_ERR;
+
+                if (pipe(p) < 0) {
+                    JimAioSetError(interp, NULL);
+                    return JIM_ERR;
+                }
+
+                return JimMakeChannelPair(interp, p, argv[1], "aio.pipe%ld", 0, mode);
             }
             break;
 #endif
+
         default:
             Jim_SetResultString(interp, "Unsupported socket type", -1);
             return JIM_ERR;
@@ -1325,10 +1412,59 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 }
 #endif /* JIM_BOOTSTRAP */
 
+/**
+ * Returns the file descriptor of a writable, newly created temp file
+ * or -1 on error.
+ * 
+ * On success, leaves the filename in the interpreter result, otherwise
+ * leaves an error message.
+ */
+int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
+{
+#ifdef HAVE_MKSTEMP
+    int fd;
+    mode_t mask;
+    Jim_Obj *filenameObj;
+
+    if (template == NULL) {
+        const char *tmpdir = getenv("TMPDIR");
+        if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
+            tmpdir = "/tmp/";
+        }
+        filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
+        if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
+            Jim_AppendString(interp, filenameObj, "/", 1);
+        }
+        Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
+    }
+    else {
+        filenameObj = Jim_NewStringObj(interp, template, -1);
+    }
+
+    mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
+
+    /* Update the template name directly with the filename */
+    fd = mkstemp(filenameObj->bytes);
+    umask(mask);
+    if (fd < 0) {
+        Jim_SetResultString(interp, "Failed to create tempfile", -1);
+        Jim_FreeNewObj(interp, filenameObj);
+        return -1;
+    }
+
+    Jim_SetResult(interp, filenameObj);
+    return fd;
+#else
+    Jim_SetResultString(interp, "tempfile not supported", -1);
+    return -1;
+#endif
+}
+
 FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
 {
     Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
 
+    /* XXX: There ought to be a supported API for this */
     if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
         return ((AioFile *) cmdPtr->u.native.privData)->fp;
     }
@@ -1346,8 +1482,10 @@ int Jim_aioInit(Jim_Interp *interp)
     Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
 #endif
 
-    /* Takeover stdin, stdout and stderr */
-    Jim_EvalGlobal(interp, "open stdin; open stdout; open stderr");
+    /* Create filehandles for stdin, stdout and stderr */
+    JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r");
+    JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w");
+    JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w");
 
     return JIM_OK;
 }
index 89a86f0..39cd168 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Implements the array command for jim
  *
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include <unistd.h>
 #include <errno.h>
 
-#include "jim.h"
-#include "jimautoconf.h"
-#include "jim-subcmd.h"
+#include <jim-subcmd.h>
 
 static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -64,58 +60,26 @@ static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    int i;
-    int len;
-    int all = 0;
-    Jim_Obj *resultObj;
     Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
-    Jim_Obj *dictObj;
-    Jim_Obj **dictValuesObj;
+    Jim_Obj *patternObj;
 
     if (!objPtr) {
         return JIM_OK;
     }
 
-    if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
-        all = 1;
-    }
+    patternObj = (argc == 1) ? NULL : argv[1];
 
-    /* If it is a dictionary or list with an even number of elements, nothing else to do */
-    if (all) {
-        if (Jim_IsDict(objPtr) || (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0)) {
+    /* Optimise the "all" case */
+    if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
+        if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
+            /* A list with an even number of elements */
             Jim_SetResult(interp, objPtr);
             return JIM_OK;
         }
     }
 
-    if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) {
-        return JIM_ERR;
-    }
-
-    if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) {
-        return JIM_ERR;
-    }
-
-    if (all) {
-        /* Return the whole array */
-        Jim_SetResult(interp, dictObj);
-    }
-    else {
-        /* Only return the matching values */
-        resultObj = Jim_NewListObj(interp, NULL, 0);
-
-        for (i = 0; i < len; i += 2) {
-            if (Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
-                Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]);
-                Jim_ListAppendElement(interp, resultObj, dictValuesObj[i + 1]);
-            }
-        }
-
-        Jim_SetResult(interp, resultObj);
-    }
-    Jim_Free(dictValuesObj);
-    return JIM_OK;
-
+    /* Return a list of keys and values where the keys match the pattern */
+    return Jim_DictValues(interp, objPtr, patternObj);
 }
 
 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -135,7 +99,6 @@ static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     int len;
     Jim_Obj *resultObj;
     Jim_Obj *objPtr;
-    Jim_Obj *dictObj;
     Jim_Obj **dictValuesObj;
 
     if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
@@ -146,11 +109,12 @@ static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
     objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
 
-    if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) {
-        return JIM_ERR;
+    if (objPtr == NULL) {
+        /* Doesn't exist, so nothing to do */
+        return JIM_OK;
     }
 
-    if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) {
+    if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
         return JIM_ERR;
     }
 
@@ -187,80 +151,105 @@ static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     return JIM_OK;
 }
 
+static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
+    if (objPtr) {
+        return Jim_DictInfo(interp, objPtr);
+    }
+    Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
+    return JIM_ERR;
+}
+
 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     int i;
     int len;
-    int rc = JIM_OK;
     Jim_Obj *listObj = argv[1];
-
-    if (Jim_GetVariable(interp, argv[0], JIM_NONE) == NULL) {
-        /* Doesn't exist, so just set the list directly */
-        return Jim_SetVariable(interp, argv[0], listObj);
-    }
+    Jim_Obj *dictObj;
 
     len = Jim_ListLength(interp, listObj);
     if (len % 2) {
         Jim_SetResultString(interp, "list must have an even number of elements", -1);
         return JIM_ERR;
     }
-    for (i = 0; i < len && rc == JIM_OK; i += 2) {
+
+    dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
+    if (!dictObj) {
+        /* Doesn't exist, so just set the list directly */
+        return Jim_SetVariable(interp, argv[0], listObj);
+    }
+    else if (Jim_DictSize(interp, dictObj) < 0) {
+        return JIM_ERR;
+    }
+
+    if (Jim_IsShared(dictObj)) {
+        dictObj = Jim_DuplicateObj(interp, dictObj);
+    }
+
+    for (i = 0; i < len; i += 2) {
         Jim_Obj *nameObj;
         Jim_Obj *valueObj;
 
         Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE);
         Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE);
 
-        rc = Jim_SetDictKeysVector(interp, argv[0], &nameObj, 1, valueObj, JIM_ERRMSG);
+        Jim_DictAddElement(interp, dictObj, nameObj, valueObj);
     }
-
-    return rc;
+    return Jim_SetVariable(interp, argv[0], dictObj);
 }
 
 static const jim_subcmd_type array_command_table[] = {
-        {       .cmd = "exists",
-                .args = "arrayName",
-                .function = array_cmd_exists,
-                .minargs = 1,
-                .maxargs = 1,
-                .description = "Does array exist?"
+        {       "exists",
+                "arrayName",
+                array_cmd_exists,
+                1,
+                1,
+                /* Description: Does array exist? */
+        },
+        {       "get",
+                "arrayName ?pattern?",
+                array_cmd_get,
+                1,
+                2,
+                /* Description: Array contents as name value list */
         },
-        {       .cmd = "get",
-                .args = "arrayName ?pattern?",
-                .function = array_cmd_get,
-                .minargs = 1,
-                .maxargs = 2,
-                .description = "Array contents as name value list"
+        {       "names",
+                "arrayName ?pattern?",
+                array_cmd_names,
+                1,
+                2,
+                /* Description: Array keys as a list */
         },
-        {       .cmd = "names",
-                .args = "arrayName ?pattern?",
-                .function = array_cmd_names,
-                .minargs = 1,
-                .maxargs = 2,
-                .description = "Array keys as a list"
+        {       "set",
+                "arrayName list",
+                array_cmd_set,
+                2,
+                2,
+                /* Description: Set array from list */
         },
-        {       .cmd = "set",
-                .args = "arrayName list",
-                .function = array_cmd_set,
-                .minargs = 2,
-                .maxargs = 2,
-                .description = "Set array from list"
+        {       "size",
+                "arrayName",
+                array_cmd_size,
+                1,
+                1,
+                /* Description: Number of elements in array */
         },
-        {       .cmd = "size",
-                .args = "arrayName",
-                .function = array_cmd_size,
-                .minargs = 1,
-                .maxargs = 1,
-                .description = "Number of elements in array"
+        {       "stat",
+                "arrayName",
+                array_cmd_stat,
+                1,
+                1,
+                /* Description: Print statistics about an array */
         },
-        {       .cmd = "unset",
-                .args = "arrayName ?pattern?",
-                .function = array_cmd_unset,
-                .minargs = 1,
-                .maxargs = 2,
-                .description = "Unset elements of an array"
+        {       "unset",
+                "arrayName ?pattern?",
+                array_cmd_unset,
+                1,
+                2,
+                /* Description: Unset elements of an array */
         },
-        {       .cmd = 0,
+        {       NULL
         }
 };
 
index 51ffb51..69fb966 100644 (file)
@@ -1,6 +1,5 @@
-
 /*
- * tcl_clock.c
+ * jim-clock.c
  *
  * Implements the clock command
  */
 #include <string.h>
 #include <stdio.h>
 #include <time.h>
-#include <sys/time.h>
 
-#include "jim.h"
 #include "jimautoconf.h"
-#include "jim-subcmd.h"
+#include <jim-subcmd.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
 
 static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -27,7 +28,7 @@ static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     time_t t;
     long seconds;
 
-    const char *format = "%a %b  %d %H:%M:%S %Z %Y";
+    const char *format = "%a %b %d %H:%M:%S %Z %Y";
 
     if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) {
         return -1;
@@ -42,7 +43,10 @@ static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     }
     t = seconds;
 
-    strftime(buf, sizeof(buf), format, localtime(&t));
+    if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) {
+        Jim_SetResultString(interp, "format string too long", -1);
+        return JIM_ERR;
+    }
 
     Jim_SetResultString(interp, buf, -1);
 
@@ -106,47 +110,51 @@ static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 }
 
 static const jim_subcmd_type clock_command_table[] = {
-    {   .cmd = "seconds",
-        .function = clock_cmd_seconds,
-        .minargs = 0,
-        .maxargs = 0,
-        .description = "Returns the current time as seconds since the epoch"
+    {   "seconds",
+        NULL,
+        clock_cmd_seconds,
+        0,
+        0,
+        /* Description: Returns the current time as seconds since the epoch */
     },
-    {   .cmd = "clicks",
-        .function = clock_cmd_micros,
-        .minargs = 0,
-        .maxargs = 0,
-        .description = "Returns the current time in 'clicks'"
+    {   "clicks",
+        NULL,
+        clock_cmd_micros,
+        0,
+        0,
+        /* Description: Returns the current time in 'clicks' */
     },
-    {   .cmd = "microseconds",
-        .function = clock_cmd_micros,
-        .minargs = 0,
-        .maxargs = 0,
-        .description = "Returns the current time in microseconds"
+    {   "microseconds",
+        NULL,
+        clock_cmd_micros,
+        0,
+        0,
+        /* Description: Returns the current time in microseconds */
     },
-    {   .cmd = "milliseconds",
-        .function = clock_cmd_millis,
-        .minargs = 0,
-        .maxargs = 0,
-        .description = "Returns the current time in milliseconds"
+    {   "milliseconds",
+        NULL,
+        clock_cmd_millis,
+        0,
+        0,
+        /* Description: Returns the current time in milliseconds */
     },
-    {   .cmd = "format",
-        .args = "seconds ?-format format?",
-        .function = clock_cmd_format,
-        .minargs = 1,
-        .maxargs = 3,
-        .description = "Format the given time"
+    {   "format",
+        "seconds ?-format format?",
+        clock_cmd_format,
+        1,
+        3,
+        /* Description: Format the given time */
     },
 #ifdef HAVE_STRPTIME
-    {   .cmd = "scan",
-        .args = "str -format format",
-        .function = clock_cmd_scan,
-        .minargs = 3,
-        .maxargs = 3,
-        .description = "Determine the time according to the given format"
+    {   "scan",
+        "str -format format",
+        clock_cmd_scan,
+        3,
+        3,
+        /* Description: Determine the time according to the given format */
     },
 #endif
-    { 0 }
+    { NULL }
 };
 
 int Jim_clockInit(Jim_Interp *interp)
old mode 100644 (file)
new mode 100755 (executable)
index a7efdc2..22ca5ff 100644 (file)
@@ -1,4 +1,3 @@
-
 /* Jim - A small embeddable Tcl interpreter
  *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
@@ -38,9 +37,9 @@
  * official policies, either expressed or implied, of the Jim Tcl Project.
  **/
 
-#include "jim.h"
 #include "jimautoconf.h"
-#include "jim-eventloop.h"
+#include <jim.h>
+#include <jim-eventloop.h>
 
 /* POSIX includes */
 #include <sys/time.h>
 #include <windows.h>
 #include <winsock.h>
 #define msleep Sleep
-#ifndef HAVE_USLEEP
-#define usleep(US) msleep((US) / 1000)
-#endif
 #else
+#ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
+#endif
 
 #ifndef HAVE_USLEEP
 /* XXX: Implement this in terms of select() or nanosleep() */
-#define usleep(US)
-#endif
+#define msleep(MS) sleep((MS) / 1000)
+#warning "sub-second sleep not supported"
+#else
 #define msleep(MS) sleep((MS) / 1000); usleep(((MS) % 1000) * 1000);
 #endif
+#endif
 
 /* --- */
 
@@ -83,10 +83,8 @@ typedef struct Jim_FileEvent
 typedef struct Jim_TimeEvent
 {
     jim_wide id;                /* time event identifier. */
-    int mode;                   /* restart, repetitive .. UK */
-    long initialms;             /* initial relativ timer value UK */
-    long when_sec;              /* seconds */
-    long when_ms;               /* milliseconds */
+    long initialms;             /* initial relative timer value */
+    jim_wide when;              /* milliseconds */
     Jim_TimeProc *timeProc;
     Jim_EventFinalizerProc *finalizerProc;
     void *clientData;
@@ -96,9 +94,10 @@ typedef struct Jim_TimeEvent
 /* Per-interp stucture containing the state of the event loop */
 typedef struct Jim_EventLoop
 {
-    jim_wide timeEventNextId;
     Jim_FileEvent *fileEventHead;
     Jim_TimeEvent *timeEventHead;
+    jim_wide timeEventNextId;   /* highest event id created, starting at 1 */
+    time_t timeBase;
     int suppress_bgerror; /* bgerror returned break, so don't call it again */
 } Jim_EventLoop;
 
@@ -160,87 +159,81 @@ void Jim_CreateFileHandler(Jim_Interp *interp, FILE * handle, int mask,
     eventLoop->fileEventHead = fe;
 }
 
-void Jim_DeleteFileHandler(Jim_Interp *interp, FILE * handle)
+/**
+ * Removes all event handlers for 'handle' that match 'mask'.
+ */
+void Jim_DeleteFileHandler(Jim_Interp *interp, FILE * handle, int mask)
 {
-    Jim_FileEvent *fe, *prev = NULL;
+    Jim_FileEvent *fe, *next, *prev = NULL;
     Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
 
-    fe = eventLoop->fileEventHead;
-    while (fe) {
-        if (fe->handle == handle) {
+    for (fe = eventLoop->fileEventHead; fe; fe = next) {
+        next = fe->next;
+        if (fe->handle == handle && (fe->mask & mask)) {
+            /* Remove this entry from the list */
             if (prev == NULL)
-                eventLoop->fileEventHead = fe->next;
+                eventLoop->fileEventHead = next;
             else
-                prev->next = fe->next;
+                prev->next = next;
             if (fe->finalizerProc)
                 fe->finalizerProc(interp, fe->clientData);
             Jim_Free(fe);
-            return;
+            continue;
         }
         prev = fe;
-        fe = fe->next;
     }
 }
 
-static void JimGetTime(long *seconds, long *milliseconds)
+/**
+ * Returns the time since interp creation in milliseconds.
+ */
+static jim_wide JimGetTime(Jim_EventLoop *eventLoop)
 {
     struct timeval tv;
 
     gettimeofday(&tv, NULL);
-    *seconds = tv.tv_sec;
-    *milliseconds = tv.tv_usec / 1000;
+
+    return (jim_wide)(tv.tv_sec - eventLoop->timeBase) * 1000 + tv.tv_usec / 1000;
 }
 
 jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds,
     Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
 {
     Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
-    jim_wide id = eventLoop->timeEventNextId++;
+    jim_wide id = ++eventLoop->timeEventNextId;
     Jim_TimeEvent *te, *e, *prev;
-    long cur_sec, cur_ms;
-
-    JimGetTime(&cur_sec, &cur_ms);
 
     te = Jim_Alloc(sizeof(*te));
     te->id = id;
-    te->mode = 0;
     te->initialms = milliseconds;
-    te->when_sec = cur_sec + milliseconds / 1000;
-    te->when_ms = cur_ms + milliseconds % 1000;
-    if (te->when_ms >= 1000) {
-        te->when_sec++;
-        te->when_ms -= 1000;
-    }
+    te->when = JimGetTime(eventLoop) + milliseconds;
     te->timeProc = proc;
     te->finalizerProc = finalizerProc;
     te->clientData = clientData;
 
     /* Add to the appropriate place in the list */
-    if (eventLoop->timeEventHead) {
-        prev = NULL;
-        for (e = eventLoop->timeEventHead; e; e = e->next) {
-            if (te->when_sec < e->when_sec || (te->when_sec == e->when_sec && te->when_ms < e->when_ms)) {
-                break;
-            }
-            prev = e;
-        }
-        if (prev) {
-            te->next = prev->next;
-            prev->next = te;
-            return id;
+    prev = NULL;
+    for (e = eventLoop->timeEventHead; e; e = e->next) {
+        if (te->when < e->when) {
+            break;
         }
+        prev = e;
+    }
+    if (prev) {
+        te->next = prev->next;
+        prev->next = te;
+    }
+    else {
+        te->next = eventLoop->timeEventHead;
+        eventLoop->timeEventHead = te;
     }
-
-    te->next = eventLoop->timeEventHead;
-    eventLoop->timeEventHead = te;
 
     return id;
 }
 
 static jim_wide JimParseAfterId(Jim_Obj *idObj)
 {
-    int len;
-    const char *tok = Jim_GetString(idObj, &len);
+    const char *tok = Jim_String(idObj);
     jim_wide id;
 
     if (strncmp(tok, "after#", 6) == 0 && Jim_StringToWide(tok + 6, &id, 10) == JIM_OK) {
@@ -306,19 +299,15 @@ jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id)
     Jim_TimeEvent *te;
     Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
 
-    if (id >= eventLoop->timeEventNextId) {
+    if (id > eventLoop->timeEventNextId) {
         return -2;              /* wrong event ID */
     }
 
     te = Jim_RemoveTimeHandler(eventLoop, id);
     if (te) {
         jim_wide remain;
-        long cur_sec, cur_ms;
 
-        JimGetTime(&cur_sec, &cur_ms);
-
-        remain = (te->when_sec - cur_sec) * 1000;
-        remain += (te->when_ms - cur_ms);
+        remain = te->when - JimGetTime(eventLoop);
         remain = (remain < 0) ? 0 : remain;
 
         Jim_FreeTimeHandler(interp, te);
@@ -331,17 +320,16 @@ jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id)
 
 /* Process every pending time event, then every pending file event
  * (that may be registered by time event callbacks just processed).
- * Without special flags the function sleeps until some file event
- * fires, or when the next time event occurrs (if any).
+ * The behaviour depends upon the setting of flags:
  *
  * If flags is 0, the function does nothing and returns.
- * if flags has JIM_ALL_EVENTS set, all the kind of events are processed.
+ * if flags has JIM_ALL_EVENTS set, all event types are processed.
  * if flags has JIM_FILE_EVENTS set, file events are processed.
  * if flags has JIM_TIME_EVENTS set, time events are processed.
- * if flags has JIM_DONT_WAIT set the function returns ASAP until all
- * the events that's possible to process without to wait are processed.
+ * if flags has JIM_DONT_WAIT set, the function returns as soon as all
+ * the events that are possible to process without waiting are processed.
  *
- * The function returns the number of events processed or -1 if
+ * Returns the number of events processed or -1 if
  * there are no matching handlers, or -2 on error.
  */
 int Jim_ProcessEvents(Jim_Interp *interp, int flags)
@@ -374,14 +362,12 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
         /* The nearest timer is always at the head of the list */
         if (eventLoop->timeEventHead) {
             Jim_TimeEvent *shortest = eventLoop->timeEventHead;
-            long now_sec, now_ms;
 
             /* Calculate the time missing for the nearest
              * timer to fire. */
-            JimGetTime(&now_sec, &now_ms);
-            sleep_ms = 1000 * (shortest->when_sec - now_sec) + (shortest->when_ms - now_ms);
+            sleep_ms = shortest->when - JimGetTime(eventLoop);
             if (sleep_ms < 0) {
-                sleep_ms = 1;
+                sleep_ms = 0;
             }
         }
         else {
@@ -430,7 +416,6 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
                 Jim_SetResultString(interp, "non-waitable filehandle", -1);
                 return -2;
             }
-            /* XXX: What about EINTR? */
         }
         else if (retval > 0) {
             fe = eventLoop->fileEventHead;
@@ -448,7 +433,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
                 if (mask) {
                     if (fe->fileProc(interp, fe->clientData, mask) != JIM_OK) {
                         /* Remove the element on handler error */
-                        Jim_DeleteFileHandler(interp, fe->handle);
+                        Jim_DeleteFileHandler(interp, fe->handle, mask);
                     }
                     processed++;
                     /* After an event is processed our file event list
@@ -474,17 +459,15 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
 
     /* Check time events */
     te = eventLoop->timeEventHead;
-    maxId = eventLoop->timeEventNextId - 1;
+    maxId = eventLoop->timeEventNextId;
     while (te) {
-        long now_sec, now_ms;
         jim_wide id;
 
         if (te->id > maxId) {
             te = te->next;
             continue;
         }
-        JimGetTime(&now_sec, &now_ms);
-        if (now_sec > te->when_sec || (now_sec == te->when_sec && now_ms >= te->when_ms)) {
+        if (JimGetTime(eventLoop) >= te->when) {
             id = te->id;
             /* Remove from the list before executing */
             Jim_RemoveTimeHandler(eventLoop, id);
@@ -554,9 +537,7 @@ static int JimELVwaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     }
     else {
         /* If a result was left, it is an error */
-        int len;
-        Jim_GetString(interp->result, &len);
-        if (len) {
+        if (Jim_Length(Jim_GetResult(interp))) {
             return JIM_ERR;
         }
     }
@@ -567,16 +548,19 @@ static int JimELVwaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         Jim_Obj *currValue;
         currValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE);
         /* Stop the loop if the vwait-ed variable changed value,
-         * or if was unset and now is set (or the contrary). */
+         * or if was unset and now is set (or the contrary)
+         * or if a signal was caught
+         */
         if ((oldValue && !currValue) ||
             (!oldValue && currValue) ||
-            (oldValue && currValue && !Jim_StringEqObj(oldValue, currValue)))
+            (oldValue && currValue && !Jim_StringEqObj(oldValue, currValue)) ||
+            Jim_CheckSignal(interp)) {
             break;
+        }
     }
     if (oldValue)
         Jim_DecrRefCount(interp, oldValue);
 
-
     if (rc == -2) {
         return JIM_ERR;
     }
@@ -683,12 +667,12 @@ static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                 jim_wide remain = 0;
 
                 id = JimParseAfterId(argv[2]);
-                if (id < 0) {
+                if (id <= 0) {
                     /* Not an event id, so search by script */
                     Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2);
                     id = JimFindAfterByScript(eventLoop, scriptObj);
                     Jim_FreeNewObj(interp, scriptObj);
-                    if (id < 0) {
+                    if (id <= 0) {
                         /* Not found */
                         break;
                     }
@@ -746,10 +730,8 @@ int Jim_eventloopInit(Jim_Interp *interp)
         return JIM_ERR;
 
     eventLoop = Jim_Alloc(sizeof(*eventLoop));
-    eventLoop->fileEventHead = NULL;
-    eventLoop->timeEventHead = NULL;
-    eventLoop->timeEventNextId = 1;
-    eventLoop->suppress_bgerror = 0;
+    memset(eventLoop, 0, sizeof(*eventLoop));
+
     Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop);
 
     Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL);
index 4da5408..3e20e6f 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
  * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
- * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
+ * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
  * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
  * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
  * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
  * are those of the authors and should not be interpreted as representing
  * official policies, either expressed or implied, of the Jim Tcl Project.
  **/
+
 /* ------ USAGE -------
- *
- * In order to use this file from other extensions include it in every
- * file where you need to call the eventloop API, also in the init
- * function of your extension call Jim_ImportEventloopAPI(interp)
- * after the Jim_InitExtension() call.
- *
- * See the UDP extension as example.
+ * See jim-aio.c as an example of an event provider.
  */
 
-
 #ifndef __JIM_EVENTLOOP_H__
 #define __JIM_EVENTLOOP_H__
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <stdio.h>
 
 typedef int Jim_FileProc(Jim_Interp *interp, void *clientData, int mask);
@@ -67,7 +65,7 @@ JIM_EXPORT void Jim_CreateFileHandler (Jim_Interp *interp,
         Jim_FileProc *proc, void *clientData,
         Jim_EventFinalizerProc *finalizerProc);
 JIM_EXPORT void Jim_DeleteFileHandler (Jim_Interp *interp,
-        FILE *handle);
+        FILE *handle, int mask);
 JIM_EXPORT jim_wide Jim_CreateTimeHandler (Jim_Interp *interp,
         jim_wide milliseconds,
         Jim_TimeProc *proc, void *clientData,
@@ -84,4 +82,8 @@ JIM_EXPORT int Jim_EvalObjBackground (Jim_Interp *interp, Jim_Obj *scriptObjPtr)
 
 int Jim_eventloopInit(Jim_Interp *interp);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __JIM_EVENTLOOP_H__ */
index 9088156..e952ee7 100644 (file)
@@ -23,8 +23,8 @@
 #include <string.h>
 #include <ctype.h>
 
-#include "jim.h"
 #include "jimautoconf.h"
+#include <jim.h>
 
 #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__)
 /* Poor man's implementation of exec with system()
@@ -81,6 +81,7 @@ int Jim_execInit(Jim_Interp *interp)
 {
     if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
         return JIM_ERR;
+
     Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
     return JIM_OK;
 }
@@ -90,10 +91,13 @@ int Jim_execInit(Jim_Interp *interp)
 #include <errno.h>
 #include <signal.h>
 
-#define XXX printf("@%s:%d\n", __FILE__, __LINE__); fflush(stdout);
-
 #if defined(__MINGW32__)
-    /* XXX: Should we use this implementation for cygwin too? */
+    /* XXX: Should we use this implementation for cygwin too? msvc? */
+    #ifndef STRICT
+    #define STRICT
+    #endif
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
     #include <fcntl.h>
 
     typedef HANDLE fdtype;
@@ -122,6 +126,7 @@ int Jim_execInit(Jim_Interp *interp)
     #include <unistd.h>
     #include <fcntl.h>
     #include <sys/wait.h>
+    #include <sys/stat.h>
 
     typedef int fdtype;
     typedef int pidtype;
@@ -136,6 +141,10 @@ int Jim_execInit(Jim_Interp *interp)
     #define JimDupFd dup
     #define JimFdOpenForRead(FD) fdopen((FD), "r")
     #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0)
+
+    #ifndef HAVE_EXECVPE
+        #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV)
+    #endif
 #endif
 
 static const char *JimStrError(void);
@@ -145,7 +154,7 @@ static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
     pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
 static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
-static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents);
+static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
 static fdtype JimOpenForWrite(const char *filename, int append);
 static int JimRewindFd(fdtype fd);
 
@@ -159,6 +168,10 @@ static const char *JimStrError(void)
     return strerror(JimErrno());
 }
 
+/*
+ * If the last character of 'objPtr' is a newline, then remove
+ * the newline character.
+ */
 static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr)
 {
     int len;
@@ -196,23 +209,6 @@ static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strOb
     return JIM_OK;
 }
 
-/*
- * If the last character of the result is a newline, then remove
- * the newline character (the newline would just confuse things).
- *
- * Note: Ideally we could do this by just reducing the length of stringrep
- *       by 1, but there is no API for this :-(
- */
-static void JimTrimTrailingNewline(Jim_Interp *interp)
-{
-    int len;
-    const char *p = Jim_GetString(Jim_GetResult(interp), &len);
-
-    if (len > 0 && p[len - 1] == '\n') {
-        Jim_SetResultString(interp, p, len - 1);
-    }
-}
-
 /**
  * Builds the environment array from $::env
  *
@@ -224,7 +220,6 @@ static void JimTrimTrailingNewline(Jim_Interp *interp)
  */
 static char **JimBuildEnv(Jim_Interp *interp)
 {
-#if defined(jim_ext_tclcompat)
     int i;
     int size;
     int num;
@@ -246,14 +241,14 @@ static char **JimBuildEnv(Jim_Interp *interp)
     /* Calculate the required size */
     num = Jim_ListLength(interp, objPtr);
     if (num % 2) {
+        /* Silently drop the last element if not a valid dictionary */
         num--;
     }
-    size = Jim_Length(objPtr);
     /* We need one \0 and one equal sign for each element.
      * A list has at least one space for each element except the first.
-     * We only need one extra char for the extra null terminator.
+     * We need one extra char for the extra null terminator and one for the equal sign.
      */
-    size++;
+    size = Jim_Length(objPtr) + 2;
 
     envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size);
     envdata = (char *)&envptr[num / 2 + 1];
@@ -277,9 +272,6 @@ static char **JimBuildEnv(Jim_Interp *interp)
     *envdata = 0;
 
     return envptr;
-#else
-    return Jim_GetEnviron();
-#endif
 }
 
 /**
@@ -289,18 +281,16 @@ static char **JimBuildEnv(Jim_Interp *interp)
  */
 static void JimFreeEnv(char **env, char **original_environ)
 {
-#ifdef jim_ext_tclcompat
     if (env != original_environ) {
         Jim_Free(env);
     }
-#endif
 }
 
 /*
- * Create error messages for unusual process exits.  An
- * extra newline gets appended to each error message, but
- * it gets removed below (in the same fashion that an
- * extra newline in the command's output is removed).
+ * Create and store an appropriate value for the global variable $::errorCode
+ * Based on pid and waitStatus.
+ *
+ * Returns JIM_OK for a normal exit with code 0, otherwise returns JIM_ERR.
  */
 static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
 {
@@ -356,15 +346,15 @@ static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
 
 struct WaitInfo
 {
-    pidtype pid;                    /* Process id of child. */
+    pidtype pid;                /* Process id of child. */
     int status;                 /* Status returned when child exited or suspended. */
     int flags;                  /* Various flag bits;  see below for definitions. */
 };
 
 struct WaitInfoTable {
-    struct WaitInfo *info;
-    int size;
-    int used;
+    struct WaitInfo *info;      /* Table of outstanding processes */
+    int size;                   /* Size of the allocated table */
+    int used;                   /* Number of entries in use */
 };
 
 /*
@@ -401,15 +391,13 @@ static struct WaitInfoTable *JimAllocWaitInfoTable(void)
  */
 static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    fdtype outputId;               /* File id for output pipe.  -1
-                                 * means command overrode. */
-    fdtype errorId;                /* File id for temporary file
-                                 * containing error output. */
+    fdtype outputId;    /* File id for output pipe. -1 means command overrode. */
+    fdtype errorId;     /* File id for temporary file containing error output. */
     pidtype *pidPtr;
     int numPids, result;
 
     /*
-     * See if the command is to be run in background;  if so, create
+     * See if the command is to be run in the background; if so, create
      * the command, detach it, and return.
      */
     if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
@@ -465,22 +453,28 @@ static void JimReapDetachedPids(struct WaitInfoTable *table)
 {
     struct WaitInfo *waitPtr;
     int count;
+    int dest;
 
     if (!table) {
         return;
     }
 
-    for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) {
+    waitPtr = table->info;
+    dest = 0;
+    for (count = table->used; count > 0; waitPtr++, count--) {
         if (waitPtr->flags & WI_DETACHED) {
             int status;
             pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG);
-            if (pid != JIM_BAD_PID) {
-                if (waitPtr != &table->info[table->used - 1]) {
-                    *waitPtr = table->info[table->used - 1];
-                }
+            if (pid == waitPtr->pid) {
+                /* Process has exited, so remove it from the table */
                 table->used--;
+                continue;
             }
         }
+        if (waitPtr != &table->info[dest]) {
+            table->info[dest] = *waitPtr;
+        }
+        dest++;
     }
 }
 
@@ -514,24 +508,11 @@ static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *
     return JIM_BAD_PID;
 }
 
-/*
- *----------------------------------------------------------------------
- *
- * JimDetachPids --
- *
- *  This procedure is called to indicate that one or more child
- *  processes have been placed in background and are no longer
- *  cared about.  These children can be cleaned up with JimReapDetachedPids().
- *
- * Results:
- *  None.
- *
- * Side effects:
- *  None.
- *
- *----------------------------------------------------------------------
+/**
+ * Indicates that one or more child processes have been placed in
+ * background and are no longer cared about.
+ * These children can be cleaned up with JimReapDetachedPids().
  */
-
 static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr)
 {
     int j;
@@ -549,6 +530,19 @@ static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr
     }
 }
 
+static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name)
+{
+    FILE *fh;
+    Jim_Obj *fhObj;
+
+    fhObj = Jim_NewStringObj(interp, name, -1);
+    Jim_IncrRefCount(fhObj);
+    fh = Jim_AioFilehandle(interp, fhObj);
+    Jim_DecrRefCount(interp, fhObj);
+
+    return fh;
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -590,6 +584,7 @@ JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **
     const char *input = NULL;   /* Describes input for pipeline, depending
                                  * on "inputFile".  NULL means take input
                                  * from stdin/pipe. */
+    int input_len = 0;          /* Length of input, if relevant */
 
 #define FILE_NAME   0           /* input/output: filename */
 #define FILE_APPEND 1           /* output only:  filename, append */
@@ -674,6 +669,7 @@ JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **
             input = arg + 1;
             if (*input == '<') {
                 inputFile = FILE_TEXT;
+                input_len = Jim_Length(argv[i]) - 2;
                 input++;
             }
             else if (*input == '@') {
@@ -682,7 +678,7 @@ JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **
             }
 
             if (!*input && ++i < argc) {
-                input = Jim_String(argv[i]);
+                input = Jim_GetString(argv[i], &input_len);
             }
         }
         else if (arg[0] == '>') {
@@ -768,17 +764,15 @@ badargs:
              * Immediate data in command.  Create temporary file and
              * put data into file.
              */
-            inputId = JimCreateTemp(interp, input);
+            inputId = JimCreateTemp(interp, input, input_len);
             if (inputId == JIM_BAD_FD) {
                 goto error;
             }
         }
         else if (inputFile == FILE_HANDLE) {
             /* Should be a file descriptor */
-            Jim_Obj *fhObj = Jim_NewStringObj(interp, input, -1);
-            FILE *fh = Jim_AioFilehandle(interp, fhObj);
+            FILE *fh = JimGetAioFilehandle(interp, input);
 
-            Jim_FreeNewObj(interp, fhObj);
             if (fh == NULL) {
                 goto error;
             }
@@ -811,10 +805,7 @@ badargs:
      */
     if (output != NULL) {
         if (outputFile == FILE_HANDLE) {
-            Jim_Obj *fhObj = Jim_NewStringObj(interp, output, -1);
-            FILE *fh = Jim_AioFilehandle(interp, fhObj);
-
-            Jim_FreeNewObj(interp, fhObj);
+            FILE *fh = JimGetAioFilehandle(interp, output);
             if (fh == NULL) {
                 goto error;
             }
@@ -858,10 +849,7 @@ badargs:
                 }
             }
             if (errorId == JIM_BAD_FD) {
-                Jim_Obj *fhObj = Jim_NewStringObj(interp, error, -1);
-                FILE *fh = Jim_AioFilehandle(interp, fhObj);
-
-                Jim_FreeNewObj(interp, fhObj);
+                FILE *fh = JimGetAioFilehandle(interp, error);
                 if (fh == NULL) {
                     goto error;
                 }
@@ -889,7 +877,7 @@ badargs:
          * to complete before reading stderr, and processes couldn't complete
          * because stderr was backed up.
          */
-        errorId = JimCreateTemp(interp, NULL);
+        errorId = JimCreateTemp(interp, NULL, 0);
         if (errorId == JIM_BAD_FD) {
             goto error;
         }
@@ -930,6 +918,11 @@ badargs:
             outputId = pipeIds[1];
         }
 
+        /* Need to do this befor vfork() */
+        if (pipe_dup_err) {
+            errorId = outputId;
+        }
+
         /* Now fork the child */
 
 #ifdef __MINGW32__
@@ -940,22 +933,6 @@ badargs:
         }
 #else
         /*
-         * Disable SIGPIPE signals:  if they were allowed, this process
-         * might go away unexpectedly if children misbehave.  This code
-         * can potentially interfere with other application code that
-         * expects to handle SIGPIPEs;  what's really needed is an
-         * arbiter for signals to allow them to be "shared".
-         */
-        if (table->info == NULL) {
-            (void)signal(SIGPIPE, SIG_IGN);
-        }
-
-        /* Need to do this befor vfork() */
-        if (pipe_dup_err) {
-            errorId = outputId;
-        }
-
-        /*
          * Make a new process and enter it into the table if the fork
          * is successful.
          */
@@ -975,10 +952,13 @@ badargs:
                 close(i);
             }
 
-            execvp(arg_array[firstArg], &arg_array[firstArg]);
+            /* Restore SIGPIPE behaviour */
+            (void)signal(SIGPIPE, SIG_DFL);
+
+            execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron());
 
             /* Need to prep an error message before vfork(), just in case */
-            fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]);
+            fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]);
             _exit(127);
         }
 #endif
@@ -1126,7 +1106,7 @@ static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr,
         }
     }
 
-    JimTrimTrailingNewline(interp);
+    Jim_RemoveTrailingNewline(Jim_GetResult(interp));
 
     return result;
 }
@@ -1135,6 +1115,21 @@ int Jim_execInit(Jim_Interp *interp)
 {
     if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG))
         return JIM_ERR;
+
+#ifdef SIGPIPE
+    /*
+     * Disable SIGPIPE signals:  if they were allowed, this process
+     * might go away unexpectedly if children misbehave.  This code
+     * can potentially interfere with other application code that
+     * expects to handle SIGPIPEs.
+     *
+     * By doing this in the init function, applications can override
+     * this later. Note that child processes have SIGPIPE restored
+     * to the default after vfork().
+     */
+    (void)signal(SIGPIPE, SIG_IGN);
+#endif
+
     Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable);
     return JIM_OK;
 }
@@ -1312,7 +1307,7 @@ static pidtype JimWaitPid(pidtype pid, int *status, int nohang)
     return pid;
 }
 
-static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents)
+static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
 {
     char name[MAX_PATH];
     HANDLE handle;
@@ -1336,7 +1331,7 @@ static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents)
             goto error;
         }
 
-        if (fwrite(contents, strlen(contents), 1, fh) != 1) {
+        if (fwrite(contents, len, 1, fh) != 1) {
             fclose(fh);
             goto error;
         }
@@ -1381,7 +1376,7 @@ static char **JimSaveEnv(char **env)
 
 static void JimRestoreEnv(char **env)
 {
-    JimFreeEnv(env, NULL);
+    JimFreeEnv(env, Jim_GetEnviron());
 }
 
 static Jim_Obj *
@@ -1467,14 +1462,12 @@ JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, f
     PROCESS_INFORMATION procInfo;
     HANDLE hProcess, h;
     char execPath[MAX_PATH];
-    char *originalName;
     pidtype pid = JIM_BAD_PID;
     Jim_Obj *cmdLineObj;
 
     if (JimWinFindExecutable(argv[0], execPath) < 0) {
         return JIM_BAD_PID;
     }
-    originalName = argv[0];
     argv[0] = execPath;
 
     hProcess = GetCurrentProcess();
@@ -1489,7 +1482,7 @@ JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, f
     ZeroMemory(&startInfo, sizeof(startInfo));
     startInfo.cb = sizeof(startInfo);
     startInfo.dwFlags   = STARTF_USESTDHANDLES;
-    startInfo.hStdInput        = INVALID_HANDLE_VALUE;
+    startInfo.hStdInput = INVALID_HANDLE_VALUE;
     startInfo.hStdOutput= INVALID_HANDLE_VALUE;
     startInfo.hStdError = INVALID_HANDLE_VALUE;
 
@@ -1581,19 +1574,17 @@ static int JimRewindFd(int fd)
     return lseek(fd, 0L, SEEK_SET);
 }
 
-static int JimCreateTemp(Jim_Interp *interp, const char *contents)
+static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len)
 {
-    char inName[] = "/tmp/tcl.tmp.XXXXXX";
+    int fd = Jim_MakeTempFile(interp, NULL);
 
-    int fd = mkstemp(inName);
     if (fd == JIM_BAD_FD) {
         Jim_SetResultErrno(interp, "couldn't create temp file");
         return -1;
     }
-    unlink(inName);
+    unlink(Jim_String(Jim_GetResult(interp)));
     if (contents) {
-        int length = strlen(contents);
-        if (write(fd, contents, length) != length) {
+        if (write(fd, contents, len) != len) {
             Jim_SetResultErrno(interp, "couldn't write temp file");
             close(fd);
             return -1;
index 7b48368..ea65f49 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include <unistd.h>
 #include <errno.h>
 #include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/time.h>
 
-#include "jim.h"
-#include "jimautoconf.h"
-#include "jim-subcmd.h"
+#include <jimautoconf.h>
+#include <jim-subcmd.h>
+
+#ifdef HAVE_UTIMES
+#include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#elif defined(_MSC_VER)
+#include <direct.h>
+#define F_OK 0
+#define W_OK 2
+#define R_OK 4
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
 
 # ifndef MAXPATHLEN
 # define MAXPATHLEN JIM_PATH_LEN
@@ -86,25 +96,31 @@ static const char *JimGetFileType(int mode)
     else if (S_ISDIR(mode)) {
         return "directory";
     }
+#ifdef S_ISCHR
     else if (S_ISCHR(mode)) {
         return "characterSpecial";
     }
+#endif
+#ifdef S_ISBLK
     else if (S_ISBLK(mode)) {
         return "blockSpecial";
     }
+#endif
+#ifdef S_ISFIFO
     else if (S_ISFIFO(mode)) {
         return "fifo";
-#ifdef S_ISLNK
     }
+#endif
+#ifdef S_ISLNK
     else if (S_ISLNK(mode)) {
         return "link";
+    }
 #endif
 #ifdef S_ISSOCK
-    }
     else if (S_ISSOCK(mode)) {
         return "socket";
-#endif
     }
+#endif
     return "unknown";
 }
 
@@ -126,54 +142,57 @@ static const char *JimGetFileType(int mode)
  *
  *----------------------------------------------------------------------
  */
-
-static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
-    jim_wide value)
+static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value)
 {
-    Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
-    Jim_Obj *valobj = Jim_NewWideObj(interp, value);
-
-    if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
-        Jim_FreeObj(interp, nameobj);
-        Jim_FreeObj(interp, valobj);
-        return JIM_ERR;
-    }
-    return JIM_OK;
+    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1));
+    Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
 }
 
-static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key,
-    const char *value)
+static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
 {
-    Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1);
-    Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1);
+    /* Just use a list to store the data */
+    Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
+
+    AppendStatElement(interp, listObj, "dev", sb->st_dev);
+    AppendStatElement(interp, listObj, "ino", sb->st_ino);
+    AppendStatElement(interp, listObj, "mode", sb->st_mode);
+    AppendStatElement(interp, listObj, "nlink", sb->st_nlink);
+    AppendStatElement(interp, listObj, "uid", sb->st_uid);
+    AppendStatElement(interp, listObj, "gid", sb->st_gid);
+    AppendStatElement(interp, listObj, "size", sb->st_size);
+    AppendStatElement(interp, listObj, "atime", sb->st_atime);
+    AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
+    AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
+    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
+    Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
+
+    /* Was a variable specified? */
+    if (varName) {
+        Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE);
+        if (objPtr) {
+            if (Jim_DictSize(interp, objPtr) < 0) {
+                /* This message matches the one from Tcl */
+                Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName);
+                Jim_FreeNewObj(interp, listObj);
+                return JIM_ERR;
+            }
 
-    if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) {
-        Jim_FreeObj(interp, nameobj);
-        Jim_FreeObj(interp, valobj);
-        return JIM_ERR;
-    }
-    return JIM_OK;
-}
+            if (Jim_IsShared(objPtr))
+                objPtr = Jim_DuplicateObj(interp, objPtr);
 
-static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb)
-{
-    if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) {
-        Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variables isn't array", varName);
-        return JIM_ERR;
+            /* Just cheat here and append as a list and convert to a dict */
+            Jim_ListAppendList(interp, objPtr, listObj);
+            Jim_DictSize(interp, objPtr);
+            Jim_InvalidateStringRep(objPtr);
+
+            Jim_FreeNewObj(interp, listObj);
+            listObj = objPtr;
+        }
+        Jim_SetVariable(interp, varName, listObj);
     }
-    set_array_int_value(interp, varName, "ino", sb->st_ino);
-    set_array_int_value(interp, varName, "mode", sb->st_mode);
-    set_array_int_value(interp, varName, "nlink", sb->st_nlink);
-    set_array_int_value(interp, varName, "uid", sb->st_uid);
-    set_array_int_value(interp, varName, "gid", sb->st_gid);
-    set_array_int_value(interp, varName, "size", sb->st_size);
-    set_array_int_value(interp, varName, "atime", sb->st_atime);
-    set_array_int_value(interp, varName, "mtime", sb->st_mtime);
-    set_array_int_value(interp, varName, "ctime", sb->st_ctime);
-    set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode));
 
     /* And also return the value */
-    Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0));
+    Jim_SetResult(interp, listObj);
 
     return JIM_OK;
 }
@@ -183,13 +202,15 @@ static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     const char *path = Jim_String(argv[0]);
     const char *p = strrchr(path, '/');
 
-    if (!p) {
+    if (!p && path[0] == '.' && path[1] == '.' && path[2] == '\0') {
+        Jim_SetResultString(interp, "..", -1);
+    } else if (!p) {
         Jim_SetResultString(interp, ".", -1);
     }
     else if (p == path) {
         Jim_SetResultString(interp, "/", -1);
     }
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(_MSC_VER)
     else if (p[-1] == ':') {
         /* z:/dir => z:/ */
         Jim_SetResultString(interp, path, p - path + 1);
@@ -251,12 +272,13 @@ static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv
 
     if (realpath(path, newname)) {
         Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1));
+        return JIM_OK;
     }
     else {
         Jim_Free(newname);
-        Jim_SetResult(interp, argv[0]);
+        Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno));
+        return JIM_ERR;
     }
-    return JIM_OK;
 #else
     Jim_SetResultString(interp, "Not implemented", -1);
     return JIM_ERR;
@@ -280,7 +302,7 @@ static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
             /* Absolute component, so go back to the start */
             last = newname;
         }
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(_MSC_VER)
         else if (strchr(part, ':')) {
             /* Absolute compontent on mingw, so go back to the start */
             last = newname;
@@ -329,10 +351,7 @@ static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
 static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode)
 {
-    const char *path = Jim_String(filename);
-    int rc = access(path, mode);
-
-    Jim_SetResultBool(interp, rc != -1);
+    Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1);
 
     return JIM_OK;
 }
@@ -349,7 +368,13 @@ static int file_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
 static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
+#ifdef X_OK
     return file_access(interp, argv[0], X_OK);
+#else
+    /* If no X_OK, just assume true. */
+    Jim_SetResultBool(interp, 1);
+    return JIM_OK;
+#endif
 }
 
 static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -406,14 +431,16 @@ static int mkdir_all(char *path)
 
     while (ok--) {
         /* Must have failed the first time, so recursively make the parent and try again */
-        char *slash = strrchr(path, '/');
+        {
+            char *slash = strrchr(path, '/');
 
-        if (slash && slash != path) {
-            *slash = 0;
-            if (mkdir_all(path) != 0) {
-                return -1;
+            if (slash && slash != path) {
+                *slash = 0;
+                if (mkdir_all(path) != 0) {
+                    return -1;
+                }
+                *slash = '/';
             }
-            *slash = '/';
         }
       first:
         if (MKDIR_DEFAULT(path) == 0) {
@@ -456,29 +483,17 @@ static int file_cmd_mkdir(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     return JIM_OK;
 }
 
-#ifdef HAVE_MKSTEMP
 static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    int fd;
-    char *filename;
-    const char *template = "/tmp/tcl.tmp.XXXXXX";
+    int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL);
 
-    if (argc >= 1) {
-        template = Jim_String(argv[0]);
-    }
-    filename = Jim_StrDup(template);
-
-    fd = mkstemp(filename);
     if (fd < 0) {
-        Jim_SetResultString(interp, "Failed to create tempfile", -1);
         return JIM_ERR;
     }
     close(fd);
 
-    Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1));
     return JIM_OK;
 }
-#endif
 
 static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -524,10 +539,7 @@ static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
     return JIM_OK;
 }
 
-#ifndef HAVE_LSTAT
-#define lstat stat
-#endif
-
+#ifdef HAVE_LSTAT
 static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
 {
     const char *path = Jim_String(filename);
@@ -538,6 +550,9 @@ static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
     }
     return JIM_OK;
 }
+#else
+#define file_lstat file_stat
+#endif
 
 static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -666,6 +681,7 @@ static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     return JIM_OK;
 }
 
+#ifdef HAVE_LSTAT
 static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     struct stat sb;
@@ -673,8 +689,11 @@ static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
         return JIM_ERR;
     }
-    return StoreStatData(interp, argv[1], &sb);
+    return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
 }
+#else
+#define file_cmd_lstat file_cmd_stat
+#endif
 
 static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -683,193 +702,191 @@ static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     if (file_stat(interp, argv[0], &sb) != JIM_OK) {
         return JIM_ERR;
     }
-    return StoreStatData(interp, argv[1], &sb);
+    return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
 }
 
 static const jim_subcmd_type file_command_table[] = {
-    {   .cmd = "atime",
-        .args = "name",
-        .function = file_cmd_atime,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Last access time"
+    {   "atime",
+        "name",
+        file_cmd_atime,
+        1,
+        1,
+        /* Description: Last access time */
     },
-    {   .cmd = "mtime",
-        .args = "name ?time?",
-        .function = file_cmd_mtime,
-        .minargs = 1,
-        .maxargs = 2,
-        .description = "Get or set last modification time"
+    {   "mtime",
+        "name ?time?",
+        file_cmd_mtime,
+        1,
+        2,
+        /* Description: Get or set last modification time */
     },
-    {   .cmd = "copy",
-        .args = "?-force? source dest",
-        .function = file_cmd_copy,
-        .minargs = 2,
-        .maxargs = 3,
-        .description = "Copy source file to destination file"
+    {   "copy",
+        "?-force? source dest",
+        file_cmd_copy,
+        2,
+        3,
+        /* Description: Copy source file to destination file */
     },
-    {   .cmd = "dirname",
-        .args = "name",
-        .function = file_cmd_dirname,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Directory part of the name"
+    {   "dirname",
+        "name",
+        file_cmd_dirname,
+        1,
+        1,
+        /* Description: Directory part of the name */
     },
-    {   .cmd = "rootname",
-        .args = "name",
-        .function = file_cmd_rootname,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Name without any extension"
+    {   "rootname",
+        "name",
+        file_cmd_rootname,
+        1,
+        1,
+        /* Description: Name without any extension */
     },
-    {   .cmd = "extension",
-        .args = "name",
-        .function = file_cmd_extension,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Last extension including the dot"
+    {   "extension",
+        "name",
+        file_cmd_extension,
+        1,
+        1,
+        /* Description: Last extension including the dot */
     },
-    {   .cmd = "tail",
-        .args = "name",
-        .function = file_cmd_tail,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Last component of the name"
+    {   "tail",
+        "name",
+        file_cmd_tail,
+        1,
+        1,
+        /* Description: Last component of the name */
     },
-    {   .cmd = "normalize",
-        .args = "name",
-        .function = file_cmd_normalize,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Normalized path of name"
+    {   "normalize",
+        "name",
+        file_cmd_normalize,
+        1,
+        1,
+        /* Description: Normalized path of name */
     },
-    {   .cmd = "join",
-        .args = "name ?name ...?",
-        .function = file_cmd_join,
-        .minargs = 1,
-        .maxargs = -1,
-        .description = "Join multiple path components"
+    {   "join",
+        "name ?name ...?",
+        file_cmd_join,
+        1,
+        -1,
+        /* Description: Join multiple path components */
     },
-    {   .cmd = "readable",
-        .args = "name",
-        .function = file_cmd_readable,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Is file readable"
+    {   "readable",
+        "name",
+        file_cmd_readable,
+        1,
+        1,
+        /* Description: Is file readable */
     },
-    {   .cmd = "writable",
-        .args = "name",
-        .function = file_cmd_writable,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Is file writable"
+    {   "writable",
+        "name",
+        file_cmd_writable,
+        1,
+        1,
+        /* Description: Is file writable */
     },
-    {   .cmd = "executable",
-        .args = "name",
-        .function = file_cmd_executable,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Is file executable"
+    {   "executable",
+        "name",
+        file_cmd_executable,
+        1,
+        1,
+        /* Description: Is file executable */
     },
-    {   .cmd = "exists",
-        .args = "name",
-        .function = file_cmd_exists,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Does file exist"
+    {   "exists",
+        "name",
+        file_cmd_exists,
+        1,
+        1,
+        /* Description: Does file exist */
     },
-    {   .cmd = "delete",
-        .args = "?-force|--? name ...",
-        .function = file_cmd_delete,
-        .minargs = 1,
-        .maxargs = -1,
-        .description = "Deletes the files or directories (must be empty unless -force)"
+    {   "delete",
+        "?-force|--? name ...",
+        file_cmd_delete,
+        1,
+        -1,
+        /* Description: Deletes the files or directories (must be empty unless -force) */
     },
-    {   .cmd = "mkdir",
-        .args = "dir ...",
-        .function = file_cmd_mkdir,
-        .minargs = 1,
-        .maxargs = -1,
-        .description = "Creates the directories"
+    {   "mkdir",
+        "dir ...",
+        file_cmd_mkdir,
+        1,
+        -1,
+        /* Description: Creates the directories */
     },
-#ifdef HAVE_MKSTEMP
-    {   .cmd = "tempfile",
-        .args = "?template?",
-        .function = file_cmd_tempfile,
-        .minargs = 0,
-        .maxargs = 1,
-        .description = "Creates a temporary filename"
+    {   "tempfile",
+        "?template?",
+        file_cmd_tempfile,
+        0,
+        1,
+        /* Description: Creates a temporary filename */
     },
-#endif
-    {   .cmd = "rename",
-        .args = "?-force? source dest",
-        .function = file_cmd_rename,
-        .minargs = 2,
-        .maxargs = 3,
-        .description = "Renames a file"
+    {   "rename",
+        "?-force? source dest",
+        file_cmd_rename,
+        2,
+        3,
+        /* Description: Renames a file */
     },
 #if defined(HAVE_READLINK)
-    {   .cmd = "readlink",
-        .args = "name",
-        .function = file_cmd_readlink,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Value of the symbolic link"
+    {   "readlink",
+        "name",
+        file_cmd_readlink,
+        1,
+        1,
+        /* Description: Value of the symbolic link */
     },
 #endif
-    {   .cmd = "size",
-        .args = "name",
-        .function = file_cmd_size,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Size of file"
+    {   "size",
+        "name",
+        file_cmd_size,
+        1,
+        1,
+        /* Description: Size of file */
     },
-    {   .cmd = "stat",
-        .args = "name var",
-        .function = file_cmd_stat,
-        .minargs = 2,
-        .maxargs = 2,
-        .description = "Stores results of stat in var array"
+    {   "stat",
+        "name ?var?",
+        file_cmd_stat,
+        1,
+        2,
+        /* Description: Returns results of stat, and may store in var array */
     },
-    {   .cmd = "lstat",
-        .args = "name var",
-        .function = file_cmd_lstat,
-        .minargs = 2,
-        .maxargs = 2,
-        .description = "Stores results of lstat in var array"
+    {   "lstat",
+        "name ?var?",
+        file_cmd_lstat,
+        1,
+        2,
+        /* Description: Returns results of lstat, and may store in var array */
     },
-    {   .cmd = "type",
-        .args = "name",
-        .function = file_cmd_type,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Returns type of the file"
+    {   "type",
+        "name",
+        file_cmd_type,
+        1,
+        1,
+        /* Description: Returns type of the file */
     },
 #ifdef HAVE_GETEUID
-    {   .cmd = "owned",
-        .args = "name",
-        .function = file_cmd_owned,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Returns 1 if owned by the current owner"
+    {   "owned",
+        "name",
+        file_cmd_owned,
+        1,
+        1,
+        /* Description: Returns 1 if owned by the current owner */
     },
 #endif
-    {   .cmd = "isdirectory",
-        .args = "name",
-        .function = file_cmd_isdirectory,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Returns 1 if name is a directory"
+    {   "isdirectory",
+        "name",
+        file_cmd_isdirectory,
+        1,
+        1,
+        /* Description: Returns 1 if name is a directory */
     },
-    {   .cmd = "isfile",
-        .args = "name",
-        .function = file_cmd_isfile,
-        .minargs = 1,
-        .maxargs = 1,
-        .description = "Returns 1 if name is a file"
+    {   "isfile",
+        "name",
+        file_cmd_isfile,
+        1,
+        1,
+        /* Description: Returns 1 if name is a file */
     },
     {
-        .cmd = 0
+        NULL
     }
 };
 
@@ -894,14 +911,14 @@ static int Jim_CdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
 static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    const int cwd_len = 2048;
-    char *cwd = malloc(cwd_len);
+    char *cwd = Jim_Alloc(MAXPATHLEN);
 
-    if (getcwd(cwd, cwd_len) == NULL) {
+    if (getcwd(cwd, MAXPATHLEN) == NULL) {
         Jim_SetResultString(interp, "Failed to get pwd", -1);
+        Jim_Free(cwd);
         return JIM_ERR;
     }
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(_MSC_VER)
     {
         /* Try to keep backlashes out of paths */
         char *p = cwd;
@@ -913,7 +930,7 @@ static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
     Jim_SetResultString(interp, cwd, -1);
 
-    free(cwd);
+    Jim_Free(cwd);
     return JIM_OK;
 }
 
index c9cde89..dc6f8ae 100644 (file)
 #include <ctype.h>
 #include <string.h>
 
-#include "jim.h"
-#include "jimautoconf.h"
+#include <jim.h>
 #include "utf8.h"
 
-#define JIM_UTF_MAX 3
 #define JIM_INTEGER_SPACE 24
 #define MAX_FLOAT_WIDTH 320
 
@@ -60,10 +58,10 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
     const char *span, *format, *formatEnd, *msg;
     int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
     static const char * const mixedXPG =
-           "cannot mix \"%\" and \"%n$\" conversion specifiers";
+            "cannot mix \"%\" and \"%n$\" conversion specifiers";
     static const char * const badIndex[2] = {
-       "not enough arguments for all format specifiers",
-       "\"%n$\" argument index out of range"
+        "not enough arguments for all format specifiers",
+        "\"%n$\" argument index out of range"
     };
     int formatLen;
     Jim_Obj *resultPtr;
@@ -76,349 +74,382 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
 
     span = format = Jim_GetString(fmtObjPtr, &formatLen);
     formatEnd = format + formatLen;
-    resultPtr = Jim_NewStringObj(interp, "", 0);
+    resultPtr = Jim_NewEmptyStringObj(interp);
 
     while (format != formatEnd) {
-       char *end;
-       int gotMinus, sawFlag;
-       int gotPrecision, useShort;
-       long width, precision;
-       int newXpg;
-       int ch;
-       int step;
-       int doubleType;
-       char pad = ' ';
-       char spec[2*JIM_INTEGER_SPACE + 12];
-       char *p;
-
-       int formatted_chars;
-       int formatted_bytes;
-       const char *formatted_buf;
-
-       step = utf8_tounicode(format, &ch);
-       format += step;
-       if (ch != '%') {
-           numBytes += step;
-           continue;
-       }
-       if (numBytes) {
-           Jim_AppendString(interp, resultPtr, span, numBytes);
-           numBytes = 0;
-       }
-
-       /*
-        * Saw a % : process the format specifier.
-        *
-        * Step 0. Handle special case of escaped format marker (i.e., %%).
-        */
-
-       step = utf8_tounicode(format, &ch);
-       if (ch == '%') {
-           span = format;
-           numBytes = step;
-           format += step;
-           continue;
-       }
-
-       /*
-        * Step 1. XPG3 position specifier
-        */
-
-       newXpg = 0;
-       if (isdigit(ch)) {
-           int position = strtoul(format, &end, 10);
-           if (*end == '$') {
-               newXpg = 1;
-               objIndex = position - 1;
-               format = end + 1;
-               step = utf8_tounicode(format, &ch);
-           }
-       }
-       if (newXpg) {
-           if (gotSequential) {
-               msg = mixedXPG;
-               goto errorMsg;
-           }
-           gotXpg = 1;
-       } else {
-           if (gotXpg) {
-               msg = mixedXPG;
-               goto errorMsg;
-           }
-           gotSequential = 1;
-       }
-       if ((objIndex < 0) || (objIndex >= objc)) {
-           msg = badIndex[gotXpg];
-           goto errorMsg;
-       }
-
-       /*
-        * Step 2. Set of flags. Also build up the sprintf spec.
-        */
-       p = spec;
-       *p++ = '%';
-
-       gotMinus = 0;
-       sawFlag = 1;
-       do {
-           switch (ch) {
-           case '-':
-               gotMinus = 1;
-               break;
-           case '0':
-               pad = ch;
-               break;
-           case ' ':
-           case '+':
-           case '#':
-               break;
-           default:
-               sawFlag = 0;
-               continue;
-           }
-           *p++ = ch;
-           format += step;
-           step = utf8_tounicode(format, &ch);
-       } while (sawFlag);
-
-       /*
-        * Step 3. Minimum field width.
-        */
-
-       width = 0;
-       if (isdigit(ch)) {
-           width = strtoul(format, &end, 10);
-           format = end;
-           step = utf8_tounicode(format, &ch);
-       } else if (ch == '*') {
-           if (objIndex >= objc - 1) {
-               msg = badIndex[gotXpg];
-               goto errorMsg;
-           }
-           if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
-               goto error;
-           }
-           if (width < 0) {
-               width = -width;
-               if (!gotMinus) {
-                   *p++ = '-';
-                   gotMinus = 1;
-               }
-           }
-           objIndex++;
-           format += step;
-           step = utf8_tounicode(format, &ch);
-       }
-
-       /*
-        * Step 4. Precision.
-        */
-
-       gotPrecision = precision = 0;
-       if (ch == '.') {
-           gotPrecision = 1;
-           format += step;
-           step = utf8_tounicode(format, &ch);
-       }
-       if (isdigit(ch)) {
-           precision = strtoul(format, &end, 10);
-           format = end;
-           step = utf8_tounicode(format, &ch);
-       } else if (ch == '*') {
-           if (objIndex >= objc - 1) {
-               msg = badIndex[gotXpg];
-               goto errorMsg;
-           }
-           if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
-               goto error;
-           }
-
-           /*
-            * TODO: Check this truncation logic.
-            */
-
-           if (precision < 0) {
-               precision = 0;
-           }
-           objIndex++;
-           format += step;
-           step = utf8_tounicode(format, &ch);
-       }
-
-       /*
-        * Step 5. Length modifier.
-        */
-
-       useShort = 0;
-       if (ch == 'h') {
-           useShort = 1;
-           format += step;
-           step = utf8_tounicode(format, &ch);
-       } else if (ch == 'l') {
-           /* Just for compatibility. All non-short integers are wide. */
-           format += step;
-           step = utf8_tounicode(format, &ch);
-           if (ch == 'l') {
-               format += step;
-               step = utf8_tounicode(format, &ch);
-           }
-       }
-
-       format += step;
-       span = format;
-
-       /*
-        * Step 6. The actual conversion character.
-        */
-
-       if (ch == 'i') {
-           ch = 'd';
-       }
-
-       doubleType = 0;
-
-       /* Each valid conversion will set:
-        * formatted_buf   - the result to be added
-        * formatted_chars - the length of formatted_buf in characters
-        * formatted_bytes - the length of formatted_buf in bytes
-        */
-       switch (ch) {
-       case '\0':
-           msg = "format string ended in middle of field specifier";
-           goto errorMsg;
-       case 's': {
-           formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
-           formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
-           if (gotPrecision && (precision < formatted_chars)) {
-               /* Need to build a (null terminated) truncated string */
-               formatted_chars = precision;
-               formatted_bytes = utf8_index(formatted_buf, precision);
-           }
-           break;
-       }
-       case 'c': {
-           jim_wide code;
-
-           if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
-               goto error;
-           }
-           /* Just store the value in the 'spec' buffer */
-           formatted_bytes = utf8_fromunicode(spec, code);
-           formatted_buf = spec;
-           formatted_chars = 1;
-           break;
-       }
-
-       case 'e':
-       case 'E':
-       case 'f':
-       case 'g':
-       case 'G':
-           doubleType = 1;
-           /* fall through */
-       case 'd':
-       case 'u':
-       case 'o':
-       case 'x':
-       case 'X': {
-           jim_wide w;
-           double d;
-           int length;
-
-           /* Fill in the width and precision */
-           if (width) {
-               p += sprintf(p, "%ld", width);
-           }
-           if (gotPrecision) {
-               p += sprintf(p, ".%ld", precision);
-           }
-
-           /* Now the modifier, and get the actual value here */
-           if (doubleType) {
-               if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
-                   goto error;
-               }
-               length = MAX_FLOAT_WIDTH;
-           }
-           else {
-               if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
-                   goto error;
-               }
-               length = JIM_INTEGER_SPACE;
-               if (useShort) {
-                   *p++ = 'h';
-                   if (ch == 'd') {
-                       w = (short)w;
-                   }
-                   else {
-                       w = (unsigned short)w;
-                   }
-               }
-               else {
-                   *p++ = 'l';
+        char *end;
+        int gotMinus, sawFlag;
+        int gotPrecision, useShort;
+        long width, precision;
+        int newXpg;
+        int ch;
+        int step;
+        int doubleType;
+        char pad = ' ';
+        char spec[2*JIM_INTEGER_SPACE + 12];
+        char *p;
+
+        int formatted_chars;
+        int formatted_bytes;
+        const char *formatted_buf;
+
+        step = utf8_tounicode(format, &ch);
+        format += step;
+        if (ch != '%') {
+            numBytes += step;
+            continue;
+        }
+        if (numBytes) {
+            Jim_AppendString(interp, resultPtr, span, numBytes);
+            numBytes = 0;
+        }
+
+        /*
+         * Saw a % : process the format specifier.
+         *
+         * Step 0. Handle special case of escaped format marker (i.e., %%).
+         */
+
+        step = utf8_tounicode(format, &ch);
+        if (ch == '%') {
+            span = format;
+            numBytes = step;
+            format += step;
+            continue;
+        }
+
+        /*
+         * Step 1. XPG3 position specifier
+         */
+
+        newXpg = 0;
+        if (isdigit(ch)) {
+            int position = strtoul(format, &end, 10);
+            if (*end == '$') {
+                newXpg = 1;
+                objIndex = position - 1;
+                format = end + 1;
+                step = utf8_tounicode(format, &ch);
+            }
+        }
+        if (newXpg) {
+            if (gotSequential) {
+                msg = mixedXPG;
+                goto errorMsg;
+            }
+            gotXpg = 1;
+        } else {
+            if (gotXpg) {
+                msg = mixedXPG;
+                goto errorMsg;
+            }
+            gotSequential = 1;
+        }
+        if ((objIndex < 0) || (objIndex >= objc)) {
+            msg = badIndex[gotXpg];
+            goto errorMsg;
+        }
+
+        /*
+         * Step 2. Set of flags. Also build up the sprintf spec.
+         */
+        p = spec;
+        *p++ = '%';
+
+        gotMinus = 0;
+        sawFlag = 1;
+        do {
+            switch (ch) {
+            case '-':
+                gotMinus = 1;
+                break;
+            case '0':
+                pad = ch;
+                break;
+            case ' ':
+            case '+':
+            case '#':
+                break;
+            default:
+                sawFlag = 0;
+                continue;
+            }
+            *p++ = ch;
+            format += step;
+            step = utf8_tounicode(format, &ch);
+        } while (sawFlag);
+
+        /*
+         * Step 3. Minimum field width.
+         */
+
+        width = 0;
+        if (isdigit(ch)) {
+            width = strtoul(format, &end, 10);
+            format = end;
+            step = utf8_tounicode(format, &ch);
+        } else if (ch == '*') {
+            if (objIndex >= objc - 1) {
+                msg = badIndex[gotXpg];
+                goto errorMsg;
+            }
+            if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) {
+                goto error;
+            }
+            if (width < 0) {
+                width = -width;
+                if (!gotMinus) {
+                    *p++ = '-';
+                    gotMinus = 1;
+                }
+            }
+            objIndex++;
+            format += step;
+            step = utf8_tounicode(format, &ch);
+        }
+
+        /*
+         * Step 4. Precision.
+         */
+
+        gotPrecision = precision = 0;
+        if (ch == '.') {
+            gotPrecision = 1;
+            format += step;
+            step = utf8_tounicode(format, &ch);
+        }
+        if (isdigit(ch)) {
+            precision = strtoul(format, &end, 10);
+            format = end;
+            step = utf8_tounicode(format, &ch);
+        } else if (ch == '*') {
+            if (objIndex >= objc - 1) {
+                msg = badIndex[gotXpg];
+                goto errorMsg;
+            }
+            if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) {
+                goto error;
+            }
+
+            /*
+             * TODO: Check this truncation logic.
+             */
+
+            if (precision < 0) {
+                precision = 0;
+            }
+            objIndex++;
+            format += step;
+            step = utf8_tounicode(format, &ch);
+        }
+
+        /*
+         * Step 5. Length modifier.
+         */
+
+        useShort = 0;
+        if (ch == 'h') {
+            useShort = 1;
+            format += step;
+            step = utf8_tounicode(format, &ch);
+        } else if (ch == 'l') {
+            /* Just for compatibility. All non-short integers are wide. */
+            format += step;
+            step = utf8_tounicode(format, &ch);
+            if (ch == 'l') {
+                format += step;
+                step = utf8_tounicode(format, &ch);
+            }
+        }
+
+        format += step;
+        span = format;
+
+        /*
+         * Step 6. The actual conversion character.
+         */
+
+        if (ch == 'i') {
+            ch = 'd';
+        }
+
+        doubleType = 0;
+
+        /* Each valid conversion will set:
+         * formatted_buf   - the result to be added
+         * formatted_chars - the length of formatted_buf in characters
+         * formatted_bytes - the length of formatted_buf in bytes
+         */
+        switch (ch) {
+        case '\0':
+            msg = "format string ended in middle of field specifier";
+            goto errorMsg;
+        case 's': {
+            formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes);
+            formatted_chars = Jim_Utf8Length(interp, objv[objIndex]);
+            if (gotPrecision && (precision < formatted_chars)) {
+                /* Need to build a (null terminated) truncated string */
+                formatted_chars = precision;
+                formatted_bytes = utf8_index(formatted_buf, precision);
+            }
+            break;
+        }
+        case 'c': {
+            jim_wide code;
+
+            if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) {
+                goto error;
+            }
+            /* Just store the value in the 'spec' buffer */
+            formatted_bytes = utf8_getchars(spec, code);
+            formatted_buf = spec;
+            formatted_chars = 1;
+            break;
+        }
+        case 'b': {
+                unsigned jim_wide w;
+                int length;
+                int i;
+                int j;
+
+                if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) {
+                    goto error;
+                }
+                length = sizeof(w) * 8;
+
+                /* XXX: width and precision not yet implemented for binary
+                 *      also flags in 'spec', e.g. #, 0, -
+                 */
+
+                /* Increase the size of the buffer if needed */
+                if (num_buffer_size < length + 1) {
+                    num_buffer_size = length + 1;
+                    num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
+                }
+
+                j = 0;
+                for (i = length; i > 0; ) {
+                        i--;
+                    if (w & ((unsigned jim_wide)1 << i)) {
+                                num_buffer[j++] = '1';
+                        }
+                        else if (j || i == 0) {
+                                num_buffer[j++] = '0';
+                        }
+                }
+                num_buffer[j] = 0;
+                formatted_chars = formatted_bytes = j;
+                formatted_buf = num_buffer;
+                break;
+        }
+
+        case 'e':
+        case 'E':
+        case 'f':
+        case 'g':
+        case 'G':
+            doubleType = 1;
+            /* fall through */
+        case 'd':
+        case 'u':
+        case 'o':
+        case 'x':
+        case 'X': {
+            jim_wide w;
+            double d;
+            int length;
+
+            /* Fill in the width and precision */
+            if (width) {
+                p += sprintf(p, "%ld", width);
+            }
+            if (gotPrecision) {
+                p += sprintf(p, ".%ld", precision);
+            }
+
+            /* Now the modifier, and get the actual value here */
+            if (doubleType) {
+                if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) {
+                    goto error;
+                }
+                length = MAX_FLOAT_WIDTH;
+            }
+            else {
+                if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) {
+                    goto error;
+                }
+                length = JIM_INTEGER_SPACE;
+                if (useShort) {
+                    if (ch == 'd') {
+                        w = (short)w;
+                    }
+                    else {
+                        w = (unsigned short)w;
+                    }
+                }
+                *p++ = 'l';
 #ifdef HAVE_LONG_LONG
-                   if (sizeof(long long) == sizeof(jim_wide)) {
-                       *p++ = 'l';
-                   }
+                if (sizeof(long long) == sizeof(jim_wide)) {
+                    *p++ = 'l';
+                }
 #endif
-               }
-           }
-
-           *p++ = (char) ch;
-           *p = '\0';
-
-           /* Adjust length for width and precision */
-           if (width > length) {
-               length = width;
-           }
-           if (gotPrecision) {
-               length += precision;
-           }
-
-           /* Increase the size of the buffer if needed */
-           if (num_buffer_size < length + 1) {
-               num_buffer_size = length + 1;
-               num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
-           }
-
-           if (doubleType) {
-               snprintf(num_buffer, length + 1, spec, d);
-           }
-           else {
-               formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
-           }
-           formatted_chars = formatted_bytes = strlen(num_buffer);
-           formatted_buf = num_buffer;
-           break;
-       }
-
-       default: {
-           /* Just reuse the 'spec' buffer */
-           spec[0] = ch;
-           spec[1] = '\0';
-           Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
-           goto error;
-       }
-       }
-
-       if (!gotMinus) {
-           while (formatted_chars < width) {
-               Jim_AppendString(interp, resultPtr, &pad, 1);
-               formatted_chars++;
-           }
-       }
-
-       Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
-
-       while (formatted_chars < width) {
-           Jim_AppendString(interp, resultPtr, &pad, 1);
-           formatted_chars++;
-       }
-
-       objIndex += gotSequential;
+            }
+
+            *p++ = (char) ch;
+            *p = '\0';
+
+            /* Adjust length for width and precision */
+            if (width > length) {
+                length = width;
+            }
+            if (gotPrecision) {
+                length += precision;
+            }
+
+            /* Increase the size of the buffer if needed */
+            if (num_buffer_size < length + 1) {
+                num_buffer_size = length + 1;
+                num_buffer = Jim_Realloc(num_buffer, num_buffer_size);
+            }
+
+            if (doubleType) {
+                snprintf(num_buffer, length + 1, spec, d);
+            }
+            else {
+                formatted_bytes = snprintf(num_buffer, length + 1, spec, w);
+            }
+            formatted_chars = formatted_bytes = strlen(num_buffer);
+            formatted_buf = num_buffer;
+            break;
+        }
+
+        default: {
+            /* Just reuse the 'spec' buffer */
+            spec[0] = ch;
+            spec[1] = '\0';
+            Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec);
+            goto error;
+        }
+        }
+
+        if (!gotMinus) {
+            while (formatted_chars < width) {
+                Jim_AppendString(interp, resultPtr, &pad, 1);
+                formatted_chars++;
+            }
+        }
+
+        Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes);
+
+        while (formatted_chars < width) {
+            Jim_AppendString(interp, resultPtr, &pad, 1);
+            formatted_chars++;
+        }
+
+        objIndex += gotSequential;
     }
     if (numBytes) {
-       Jim_AppendString(interp, resultPtr, span, numBytes);
+        Jim_AppendString(interp, resultPtr, span, numBytes);
     }
 
     Jim_Free(num_buffer);
diff --git a/jim/jim-history.c b/jim/jim-history.c
new file mode 100644 (file)
index 0000000..9a56e04
--- /dev/null
@@ -0,0 +1,122 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "jim.h"
+#include "jimautoconf.h"
+#include "jim-subcmd.h"
+
+static int history_cmd_getline(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+    char *line = Jim_HistoryGetline(Jim_String(argv[0]));
+
+    /* On EOF returns -1 if varName was specified; otherwise the empty string. */
+    if (line == NULL) {
+        if (argc == 2) {
+            Jim_SetResultInt(interp, -1);
+        }
+        return JIM_OK;
+    }
+
+    objPtr = Jim_NewStringObjNoAlloc(interp, line, -1);
+
+    /* Returns the length of the string if varName was specified */
+    if (argc == 2) {
+        if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
+            Jim_FreeNewObj(interp, objPtr);
+            return JIM_ERR;
+        }
+        Jim_SetResultInt(interp, Jim_Length(objPtr));
+    }
+    else {
+        Jim_SetResult(interp, objPtr);
+    }
+    return JIM_OK;
+}
+
+static int history_cmd_load(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_HistoryLoad(Jim_String(argv[0]));
+    return JIM_OK;
+}
+
+static int history_cmd_save(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_HistorySave(Jim_String(argv[0]));
+    return JIM_OK;
+}
+
+static int history_cmd_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_HistoryAdd(Jim_String(argv[0]));
+    return JIM_OK;
+}
+
+static int history_cmd_show(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_HistoryShow();
+    return JIM_OK;
+}
+
+static const jim_subcmd_type history_command_table[] = {
+    {   "getline",
+        "prompt ?varname?",
+        history_cmd_getline,
+        1,
+        2,
+        /* Description: Reads one line from the user. Similar to gets. */
+    },
+    {   "load",
+        "filename",
+        history_cmd_load,
+        1,
+        1,
+        /* Description: Loads history from the given file, if possible */
+    },
+    {   "save",
+        "filename",
+        history_cmd_save,
+        1,
+        1,
+        /* Description: Saves history to the given file */
+    },
+    {   "add",
+        "line",
+        history_cmd_add,
+        1,
+        1,
+        /* Description: Adds the line to the history ands saves */
+    },
+    {   "show",
+        NULL,
+        history_cmd_show,
+        0,
+        0,
+        /* Description: Displays the history */
+    },
+    { NULL }
+};
+
+static int JimHistorySubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, history_command_table, argc, argv), argc, argv);
+}
+
+static void JimHistoryDelProc(Jim_Interp *interp, void *privData)
+{
+    Jim_Free(privData);
+}
+
+int Jim_historyInit(Jim_Interp *interp)
+{
+    void **history;
+    if (Jim_PackageProvide(interp, "history", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    history = Jim_Alloc(sizeof(*history));
+    *history = NULL;
+
+    Jim_CreateCommand(interp, "history", JimHistorySubCmdProc, history, JimHistoryDelProc);
+    return JIM_OK;
+}
index 658e8d8..f07eea1 100644 (file)
@@ -1,17 +1,25 @@
 #include <errno.h>
 #include <string.h>
-#include "jim.h"
+
 #include "jimautoconf.h"
+#include <jim.h>
 
 #ifdef USE_LINENOISE
 #include <unistd.h>
 #include "linenoise.h"
 #else
-
 #define MAX_LINE_LEN 512
+#endif
 
-static char *linenoise(const char *prompt)
+/**
+ * Returns an allocated line, or NULL if EOF.
+ */
+char *Jim_HistoryGetline(const char *prompt)
 {
+#ifdef USE_LINENOISE
+    return linenoise(prompt);
+#else
+    int len;
     char *line = malloc(MAX_LINE_LEN);
 
     fputs(prompt, stdout);
@@ -21,9 +29,47 @@ static char *linenoise(const char *prompt)
         free(line);
         return NULL;
     }
+    len = strlen(line);
+    if (len && line[len - 1] == '\n') {
+        line[len - 1] = '\0';
+    }
     return line;
+#endif
+}
+
+void Jim_HistoryLoad(const char *filename)
+{
+#ifdef USE_LINENOISE
+    linenoiseHistoryLoad(filename);
+#endif
 }
+
+void Jim_HistoryAdd(const char *line)
+{
+#ifdef USE_LINENOISE
+    linenoiseHistoryAdd(line);
 #endif
+}
+
+void Jim_HistorySave(const char *filename)
+{
+#ifdef USE_LINENOISE
+    linenoiseHistorySave(filename);
+#endif
+}
+
+void Jim_HistoryShow(void)
+{
+#ifdef USE_LINENOISE
+    /* built-in history command */
+    int i;
+    int len;
+    char **history = linenoiseHistory(&len);
+    for (i = 0; i < len; i++) {
+        printf("%4d %s\n", i + 1, history[i]);
+    }
+#endif
+}
 
 int Jim_InteractivePrompt(Jim_Interp *interp)
 {
@@ -37,11 +83,11 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
         int history_len = strlen(home) + sizeof("/.jim_history");
         history_file = Jim_Alloc(history_len);
         snprintf(history_file, history_len, "%s/.jim_history", home);
-        linenoiseHistoryLoad(history_file);
+        Jim_HistoryLoad(history_file);
     }
 #endif
 
-    printf("Welcome to Jim version %d.%d" JIM_NL,
+    printf("Welcome to Jim version %d.%d\n",
         JIM_VERSION / 100, JIM_VERSION % 100);
     Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1");
 
@@ -74,12 +120,13 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
             int len;
             char *line;
 
-            line = linenoise(prompt);
+            line = Jim_HistoryGetline(prompt);
             if (line == NULL) {
                 if (errno == EINTR) {
                     continue;
                 }
                 Jim_DecrRefCount(interp, scriptObjPtr);
+                retcode = JIM_OK;
                 goto out;
             }
             if (Jim_Length(scriptObjPtr) != 0) {
@@ -99,29 +146,22 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
 #ifdef USE_LINENOISE
         if (strcmp(str, "h") == 0) {
             /* built-in history command */
-            int i;
-            int len;
-            char **history = linenoiseHistory(&len);
-            for (i = 0; i < len; i++) {
-                printf("%4d %s\n", i + 1, history[i]);
-            }
+            Jim_HistoryShow();
             Jim_DecrRefCount(interp, scriptObjPtr);
             continue;
         }
 
-        linenoiseHistoryAdd(Jim_String(scriptObjPtr));
+        Jim_HistoryAdd(Jim_String(scriptObjPtr));
         if (history_file) {
-            linenoiseHistorySave(history_file);
+            Jim_HistorySave(history_file);
         }
 #endif
         retcode = Jim_EvalObj(interp, scriptObjPtr);
         Jim_DecrRefCount(interp, scriptObjPtr);
 
-
-
         if (retcode == JIM_EXIT) {
-            Jim_Free(history_file);
-            return JIM_EXIT;
+            retcode = JIM_EXIT;
+            break;
         }
         if (retcode == JIM_ERR) {
             Jim_MakeErrorMessage(interp);
@@ -133,5 +173,5 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
     }
   out:
     Jim_Free(history_file);
-    return JIM_OK;
+    return retcode;
 }
index 4dc6ed2..a449931 100644 (file)
@@ -1,7 +1,8 @@
-#include "jim.h"
-#include "jimautoconf.h"
 #include <string.h>
 
+#include "jimautoconf.h"
+#include <jim.h>
+
 /* -----------------------------------------------------------------------------
  * Dynamic libraries support (WIN32 not supported)
  * ---------------------------------------------------------------------------*/
@@ -19,6 +20,8 @@
     #define RTLD_LOCAL 0
 #endif
 
+static void JimFreeLoadHandles(Jim_Interp *interp, void *data);
+
 /**
  * Note that Jim_LoadLibrary() requires a path to an existing file.
  *
@@ -40,7 +43,8 @@ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
         const char *pkgname;
         int pkgnamelen;
         char initsym[40];
-        int (*onload) (Jim_Interp *);
+        typedef int jim_module_init_func_type(Jim_Interp *);
+        jim_module_init_func_type *onload;
 
         pt = strrchr(pathName, '/');
         if (pt) {
@@ -58,17 +62,19 @@ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
         }
         snprintf(initsym, sizeof(initsym), "Jim_%.*sInit", pkgnamelen, pkgname);
 
-        if ((onload = dlsym(handle, initsym)) == NULL) {
+        if ((onload = (jim_module_init_func_type *)dlsym(handle, initsym)) == NULL) {
             Jim_SetResultFormatted(interp,
                 "No %s symbol found in extension %s", initsym, pathName);
         }
         else if (onload(interp) != JIM_ERR) {
             /* Add this handle to the stack of handles to be freed */
-            if (!interp->loadHandles) {
-                interp->loadHandles = Jim_Alloc(sizeof(*interp->loadHandles));
-                Jim_InitStack(interp->loadHandles);
+            Jim_Stack *loadHandles = Jim_GetAssocData(interp, "load::handles");
+            if (loadHandles == NULL) {
+                loadHandles = Jim_Alloc(sizeof(*loadHandles));
+                Jim_InitStack(loadHandles);
+                Jim_SetAssocData(interp, "load::handles", JimFreeLoadHandles, loadHandles);
             }
-            Jim_StackPush(interp->loadHandles, handle);
+            Jim_StackPush(loadHandles, handle);
 
             Jim_SetEmptyResult(interp);
 
@@ -86,11 +92,14 @@ static void JimFreeOneLoadHandle(void *handle)
     dlclose(handle);
 }
 
-void Jim_FreeLoadHandles(Jim_Interp *interp)
+static void JimFreeLoadHandles(Jim_Interp *interp, void *data)
 {
-    if (interp->loadHandles) {
-        Jim_FreeStackElements(interp->loadHandles, JimFreeOneLoadHandle);
-        Jim_Free(interp->loadHandles);
+    Jim_Stack *handles = data;
+
+    if (handles) {
+        Jim_FreeStackElements(handles, JimFreeOneLoadHandle);
+        Jim_FreeStack(handles);
+        Jim_Free(handles);
     }
 }
 
diff --git a/jim/jim-mk.cpp b/jim/jim-mk.cpp
new file mode 100644 (file)
index 0000000..8ff1b32
--- /dev/null
@@ -0,0 +1,2276 @@
+#include <string.h>
+#include <ctype.h>
+#include <new>
+#include <mk4.h>
+
+#include "jim.h"
+#include "jimautoconf.h"
+#include "jim-subcmd.h"
+
+extern "C" { /* The whole file is essentially C */
+
+#define MK_PROPERTY_BINARY  'B'
+#define MK_PROPERTY_INT     'I'
+#define MK_PROPERTY_LONG    'L'
+#define MK_PROPERTY_FLOAT   'F'
+#define MK_PROPERTY_DOUBLE  'D'
+#define MK_PROPERTY_STRING  'S'
+#define MK_PROPERTY_VIEW    'V'
+
+#define MK_MODE_ORIGINAL    -1
+#define MK_MODE_READONLY    0
+#define MK_MODE_READWRITE   1
+#define MK_MODE_EXTEND      2
+
+#define MK_CMD_LEN 32
+#define JIM_CURSOR_SPACE (35+JIM_REFERENCE_TAGLEN + 1 + 20)
+#define JIM_POSITION_SPACE 32
+#define MK_VERSION_SPACE 16
+#define JIM_MK_DESCR_LEN 64 /* Default, will be reallocated if needed */
+
+#define isnamech(c) ( (c) && !strchr(":,[^]!", (c)) )
+
+#ifndef max
+#define max(x, y) ((x) >= (y) ? (x) : (y))
+#endif
+
+/* utilities */
+static int JimCheckMkName(Jim_Interp *interp, Jim_Obj *name, const char *type);
+static const char *JimMkTypeName(char type);
+static Jim_Obj *JimFromMkDescription(Jim_Interp *interp, const char *descr, const char **endPtr);
+static int JimToMkDescription(Jim_Interp *interp, Jim_Obj *obj, char **descrPtr);
+static Jim_Obj *JimGetMkValue(Jim_Interp *interp, c4_Cursor cur, const c4_Property &prop);
+static int JimSetMkValue(Jim_Interp *interp, c4_Cursor cur, const c4_Property &prop, Jim_Obj *obj);
+
+static int JimPipelineBoundary(int argc, Jim_Obj *const *argv);
+
+/* property object */
+static Jim_Obj *JimNewPropertyObj (Jim_Interp *interp, c4_Property prop);
+static int JimGetProperty (Jim_Interp *interp, Jim_Obj *obj,
+    c4_View view, const char *what, const c4_Property **propPtr);
+static int JimGetPropertyTyped (Jim_Interp *interp, Jim_Obj *obj,
+    char type, const c4_Property **propPtr);
+static int JimGetNewProperty (Jim_Interp *interp, Jim_Obj *obj,
+    c4_View view, char type, const c4_Property **propPtr);
+static int JimGetProperties (Jim_Interp *interp, int objc, Jim_Obj *const *objv,
+    c4_View view, c4_View *propsPtr);
+static Jim_Obj *JimViewPropertiesList (Jim_Interp *interp, c4_View view);
+
+/* cursor object */
+static int JimGetPosition (Jim_Interp *interp, Jim_Obj *obj, c4_View view, int *indexPtr);
+static int JimGetCursor (Jim_Interp *interp, Jim_Obj *obj, c4_Cursor *curPtr);
+static int JimGetCursorView (Jim_Interp *interp, Jim_Obj *obj,
+    Jim_Obj **viewObjPtr);
+static int JimCursorPos (Jim_Interp *interp, Jim_Obj *obj, Jim_Obj **posObjPtr);
+static int JimIncrCursor (Jim_Interp *interp, Jim_Obj *obj, int offset);
+static int JimSeekCursor (Jim_Interp *interp, Jim_Obj *obj, Jim_Obj *posObj);
+
+/* Also accepts JIM_ERRMSG */
+#define JIM_CURSOR_GET      (1 << JIM_PRIV_FLAG_SHIFT)
+#define JIM_CURSOR_SET      (2 << JIM_PRIV_FLAG_SHIFT)
+#define JIM_CURSOR_INSERT   (4 << JIM_PRIV_FLAG_SHIFT)
+
+static int JimCheckCursor (Jim_Interp *interp, Jim_Obj *curObj, int flags);
+
+/* view handle */
+static Jim_Obj *JimNewViewObj (Jim_Interp *interp, c4_View view);
+static int JimGetView (Jim_Interp *interp, Jim_Obj *obj, c4_View *viewPtr);
+static void JimPinView (Jim_Interp *interp, Jim_Obj *obj);
+
+/* -------------------------------------------------------------------------
+ * Utilities
+ * ------------------------------------------------------------------------- */
+
+static int JimCheckMkName(Jim_Interp *interp, Jim_Obj *name, const char *type)
+{
+    const char *s;
+    int i, len;
+
+    s = Jim_GetString(name, &len);
+
+    if (len > 0 && s[0] == '-')
+        goto err;
+    for (i = 0; i < len; i++) {
+        if (!isnamech(s[i]))
+            goto err;
+    }
+
+    return JIM_OK;
+
+  err:
+    Jim_SetResultFormatted(interp, "expected %s name but got \"%#s\"", type ? type : "property", name);
+    return JIM_ERR;
+}
+
+static const char *const jim_mktype_options[] = {
+    "-integer",
+    "-long",
+    "-float",
+    "-double",
+    "-string",
+    "-subview",
+    /* FIXME "-binary", */
+    0
+};
+
+static const char *const jim_mktype_names[] = {
+    "integer",
+    "long",
+    "float",
+    "double",
+    "string",
+    "subview",
+    /* FIXME "binary", */
+    0
+};
+
+static const char jim_mktype_types[] = {
+    MK_PROPERTY_INT,
+    MK_PROPERTY_LONG,
+    MK_PROPERTY_FLOAT,
+    MK_PROPERTY_DOUBLE,
+    MK_PROPERTY_STRING,
+    MK_PROPERTY_VIEW,
+    /* MK_PROPERTY_BINARY, */
+};
+
+#define JIM_MKTYPES ((int)(sizeof(jim_mktype_types) / sizeof(jim_mktype_types[0])))
+
+static const char *JimMkTypeName(char type)
+{
+    int i;
+
+    for (i = 0; i < JIM_MKTYPES; i++) {
+        if (type == jim_mktype_types[i])
+            return jim_mktype_names[i];
+    }
+    return "(unknown type)";
+}
+
+static Jim_Obj *JimFromMkDescription(Jim_Interp *interp, const char *descr, const char **endPtr)
+{
+    Jim_Obj *result;
+    const char *delim;
+
+    result = Jim_NewListObj(interp, NULL, 0);
+    for (;;) {
+        if (*descr == ']') {
+            descr++;
+            break;
+        }
+        else if (*descr == '\0')
+            break;
+        else if (*descr == ',')
+            descr++;
+
+        delim = strpbrk(descr, ",:[]");
+        /* JimPanic((!delim, "Invalid Metakit description string")); */
+
+        Jim_ListAppendElement(interp, result,
+            Jim_NewStringObj(interp, descr, delim - descr));
+
+        if (delim[0] == '[') {
+            Jim_ListAppendElement(interp, result,
+                JimFromMkDescription(interp, delim + 1, &descr));
+        }
+        else if (delim[0] == ':') {
+            Jim_ListAppendElement(interp, result,
+                Jim_NewStringObj(interp, JimMkTypeName(delim[1]), -1));
+            descr = delim + 2;
+        }
+        else {
+            /* Seems that Metakit never generates descriptions without type
+             * tags, but let's handle this just to be safe
+             */
+
+            Jim_ListAppendElement(interp, result,
+                Jim_NewStringObj(interp, JimMkTypeName(MK_PROPERTY_STRING), -1));
+        }
+    }
+
+    if (endPtr)
+        *endPtr = descr;
+    return result;
+}
+
+/* This allocates the buffer once per user call and stores it in a static
+ * variable. Recursive calls are distinguished by descrPtr == NULL.
+ */
+static int JimToMkDescription(Jim_Interp *interp, Jim_Obj *descrObj, char **descrPtr)
+{
+    static char *descr, *outPtr;
+    static int bufSize;
+
+    #define ENLARGE(size) do {                                   \
+        if ((descr - outPtr) + (size) > bufSize) {               \
+            bufSize = max(2*bufSize, (descr - outPtr) + (size)); \
+            descr = (char *)Jim_Realloc(descr, bufSize);         \
+        }                                                        \
+    } while(0)
+
+    int i, count;
+    Jim_Obj *name, *struc;
+
+    const char *rep;
+    int len;
+
+    count = Jim_ListLength(interp, descrObj);
+    if (count % 2) {
+        Jim_SetResultString(interp,
+            "view description must have an even number of elements", -1);
+        return JIM_ERR;
+    }
+
+    if (descrPtr) {
+        descr = (char *)Jim_Alloc(bufSize = JIM_MK_DESCR_LEN);
+        outPtr = descr;
+    }
+
+    for (i = 0; i < count; i += 2) {
+        Jim_ListIndex(interp, descrObj, i, &name, 0);
+        Jim_ListIndex(interp, descrObj, i + 1, &struc, 0);
+
+        if (JimCheckMkName(interp, name, NULL) != JIM_OK)
+            goto err;
+
+        rep = Jim_GetString(name, &len);
+        ENLARGE(len + 3); /* At least :T, or [], */
+        memcpy(outPtr, rep, len);
+        outPtr += len;
+
+        if (Jim_ListLength(interp, struc) == 1) {
+            int idx;
+
+            if (Jim_GetEnum(interp, struc, jim_mktype_names, &idx,
+                    "property type", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
+                goto err;
+
+            *outPtr++ = ':';
+            *outPtr++ = jim_mktype_types[idx];
+        }
+        else {
+            *outPtr++ = '[';
+
+            if (JimToMkDescription(interp, struc, NULL) != JIM_OK)
+                goto err;
+
+            ENLARGE(2); /* bracket, comma */
+            *outPtr++ = ']';
+        }
+
+        *outPtr++ = ',';
+    }
+    *(--outPtr) = '\0';
+
+    #undef ENLARGE
+
+    if (descrPtr) {
+        *descrPtr = (char *)Jim_Realloc(descr, strlen(descr) + 1);
+        descr = NULL; /* Safety measure */
+    }
+
+    return JIM_OK;
+
+  err:
+
+    if (descrPtr)
+        Jim_Free(descr);
+
+    return JIM_ERR;
+}
+
+static Jim_Obj *JimGetMkValue(Jim_Interp *interp, c4_Cursor cur, const c4_Property &prop)
+{
+    switch (prop.Type()) {
+        case MK_PROPERTY_INT:
+            return Jim_NewIntObj(interp, ((c4_IntProp &)prop).Get(*cur));
+        case MK_PROPERTY_LONG:
+            return Jim_NewIntObj(interp, ((c4_LongProp &)prop).Get(*cur));
+        case MK_PROPERTY_FLOAT:
+            return Jim_NewDoubleObj(interp, ((c4_FloatProp &)prop).Get(*cur));
+        case MK_PROPERTY_DOUBLE:
+            return Jim_NewDoubleObj(interp, ((c4_DoubleProp &)prop).Get(*cur));
+        case MK_PROPERTY_STRING:
+            return Jim_NewStringObj(interp, ((c4_StringProp &)prop).Get(*cur), -1);
+        case MK_PROPERTY_VIEW:
+            return JimNewViewObj(interp, ((c4_ViewProp &)prop).Get(*cur));
+
+        case MK_PROPERTY_BINARY:
+            /* FIXME */
+        default:
+            /* FIXME Something more meaningful here? */
+            return Jim_NewEmptyStringObj(interp);
+    }
+}
+
+static int JimSetMkValue(Jim_Interp *interp, c4_Cursor cur, const c4_Property &prop, Jim_Obj *obj)
+{
+    switch (prop.Type()) {
+        case MK_PROPERTY_INT: {
+            jim_wide value;
+
+            if (Jim_GetWide(interp, obj, &value) != JIM_OK)
+                return JIM_ERR;
+
+            ((c4_IntProp &)prop).Set(*cur, value);
+            return JIM_OK;
+        }
+        case MK_PROPERTY_LONG: {
+            jim_wide value;
+
+            if (Jim_GetWide(interp, obj, &value) != JIM_OK)
+                return JIM_ERR;
+
+            ((c4_LongProp &)prop).Set(*cur, value);
+            return JIM_OK;
+        }
+        case MK_PROPERTY_FLOAT: {
+            double value;
+
+            if (Jim_GetDouble(interp, obj, &value) != JIM_OK)
+                return JIM_ERR;
+
+            ((c4_FloatProp &)prop).Set(*cur, value);
+            return JIM_OK;
+        }
+        case MK_PROPERTY_DOUBLE: {
+            double value;
+
+            if (Jim_GetDouble(interp, obj, &value) != JIM_OK)
+                return JIM_ERR;
+
+            ((c4_DoubleProp &)prop).Set(*cur, value);
+            return JIM_OK;
+        }
+        case MK_PROPERTY_STRING: {
+            int len;
+            const char *rep;
+
+            rep = Jim_GetString(obj, &len);
+            if (len != (int)strlen(rep)) {
+                Jim_SetResultString(interp, "null characters are not allowed in Metakit strings", -1);
+                return JIM_ERR;
+            }
+
+            ((c4_StringProp &)prop).Set(*cur, rep);
+            return JIM_OK;
+        }
+        case MK_PROPERTY_VIEW: {
+            c4_View value;
+
+            if (JimGetView(interp, obj, &value) != JIM_OK)
+                return JIM_ERR;
+
+            ((c4_ViewProp &)prop).Set(*cur, value);
+        }
+        case MK_PROPERTY_BINARY:
+            /* FIXME */
+        default:
+            Jim_SetResultString(interp, "unsupported Metakit type", -1);
+            return JIM_ERR;
+    }
+}
+
+static int JimPipelineBoundary(int argc, Jim_Obj *const *argv) {
+    const char *rep;
+    int pipe, len;
+
+    for (pipe = 0; pipe < argc; pipe++) {
+        rep = Jim_GetString(argv[pipe], &len);
+        if (len == 1 && rep[0] == '|')
+            break;
+    }
+    return pipe;
+}
+
+/* -------------------------------------------------------------------------
+ * Property object
+ * ------------------------------------------------------------------------- */
+
+#define JimPropertyValue(o) ((c4_Property *)((o)->internalRep.ptr))
+
+static void FreePropertyInternalRep(Jim_Interp *interp, Jim_Obj *obj)
+{
+    delete JimPropertyValue(obj);
+}
+
+static void DupPropertyInternalRep(Jim_Interp *interp, Jim_Obj *oldObj, Jim_Obj *newObj)
+{
+    newObj->internalRep.ptr = new c4_Property(*JimPropertyValue(oldObj));
+    newObj->typePtr = oldObj->typePtr;
+}
+
+static void UpdateStringOfProperty(Jim_Obj* obj)
+{
+    const char *name = JimPropertyValue(obj)->Name();
+    int len = strlen(name);
+
+    obj->bytes = (char *) Jim_Alloc(len + 1);
+    memcpy(obj->bytes, name, len + 1);
+    obj->length = len;
+}
+
+static Jim_ObjType propertyObjType = {
+    "mk.property",
+    FreePropertyInternalRep,
+    DupPropertyInternalRep,
+    UpdateStringOfProperty,
+    JIM_TYPE_NONE
+};
+
+static int JimGetProperty(Jim_Interp *interp, Jim_Obj *obj, c4_View view, const char *name, const c4_Property **propPtr)
+{
+    int index;
+
+    if (obj->typePtr == &propertyObjType) {
+        index = view.FindProperty(JimPropertyValue(obj)->GetId());
+    }
+    else {
+        if (JimCheckMkName(interp, obj, name) != JIM_OK)
+            return JIM_ERR;
+        index = view.FindPropIndexByName(Jim_String(obj));
+    }
+
+    if (index != -1) {
+        *propPtr = &view.NthProperty(index);
+        return JIM_OK;
+    }
+    else {
+        Jim_SetResultFormatted(interp, "%s \"%#s\" does not exist",
+            name ? name : "property", obj);
+        return JIM_ERR;
+    }
+}
+
+static int JimGetPropertyTyped(Jim_Interp *interp, Jim_Obj *obj, char type, const c4_Property **propPtr)
+{
+    c4_Property *prop;
+
+    if (obj->typePtr == &propertyObjType) {
+        if (JimPropertyValue(obj)->Type() != type) {
+            /* coerce the property type */
+
+            prop = new c4_Property(type, JimPropertyValue(obj)->Name());
+            delete JimPropertyValue(obj);
+            obj->internalRep.ptr = prop;
+        }
+    }
+    else {
+        if (JimCheckMkName(interp, obj, NULL) != JIM_OK)
+            return JIM_ERR;
+
+        prop = new c4_Property(type, Jim_String(obj));
+
+        Jim_FreeIntRep(interp, obj);
+        obj->typePtr = &propertyObjType;
+        obj->internalRep.ptr = (void *)prop;
+    }
+
+    *propPtr = JimPropertyValue(obj);
+    return JIM_OK;
+}
+
+static int JimGetNewProperty(Jim_Interp *interp, Jim_Obj *obj, c4_View view, char type, const c4_Property **propPtr)
+{
+    const c4_Property *newp, *prop;
+
+    if (JimGetPropertyTyped(interp, obj, type, &newp) != JIM_OK)
+        return JIM_ERR;
+
+    prop = &view.NthProperty(view.AddProperty(*newp));
+
+    if (prop->Type() != newp->Type()) {
+        Jim_SetResultFormatted(interp, "property \"%#s\" is %s, not %s",
+            obj, JimMkTypeName(prop->Type()), JimMkTypeName(newp->Type()));
+        return JIM_ERR;
+    }
+
+    *propPtr = prop;
+    return JIM_OK;
+}
+
+static int JimGetProperties(Jim_Interp *interp, int objc, Jim_Obj *const *objv, c4_View view, c4_View *propsPtr)
+{
+    int i;
+    const c4_Property *prop;
+    c4_View props;
+
+    for (i = 0; i < objc; i++) {
+        if (JimGetProperty(interp, objv[i], view, NULL, &prop) != JIM_OK)
+            return JIM_ERR;
+
+        props.AddProperty(*prop);
+    }
+
+    *propsPtr = props;
+    return JIM_OK;
+}
+
+static Jim_Obj *JimNewPropertyObj(Jim_Interp *interp, c4_Property prop)
+{
+    Jim_Obj *obj;
+
+    obj = Jim_NewObj(interp);
+    obj->typePtr = &propertyObjType;
+    obj->bytes = NULL;
+    obj->internalRep.ptr = new c4_Property(prop);
+    return obj;
+}
+
+/* -------------------------------------------------------------------------
+ * Cursor object
+ * ------------------------------------------------------------------------- */
+
+/* Position ---------------------------------------------------------------- */
+
+/* A normal position if endFlag == 0; otherwise an offset from end+1 (!) */
+typedef struct MkPosition {
+    int index;
+    int endFlag;
+} MkPosition;
+
+/* This is mostly the same as SetIndexFromAny, but preserves more information
+ * and allows multiple [+-]integer parts.
+ */
+static int GetPosition(Jim_Interp *interp, Jim_Obj *obj, MkPosition *posPtr)
+{
+    MkPosition pos;
+    const char *rep;
+    char *end;
+    int sign, offset;
+
+    rep = Jim_String(obj);
+
+    if (strncmp(rep, "end", 3) == 0) {
+        pos.endFlag = 1;
+        pos.index = -1;
+
+        rep += 3;
+    }
+    else {
+        pos.endFlag = 0;
+        pos.index = strtol(rep, &end, 10);
+        if (end == rep)
+            goto err;
+
+        rep = end;
+    }
+
+    while ((rep[0] == '+') || (rep[0] == '-')) {
+        sign = (rep[0] == '+' ? 1 : -1);
+        rep++;
+
+        offset = strtol(rep, &end, 10);
+        if (end == rep)
+            goto err;
+
+        pos.index += sign * offset;
+        rep = end;
+    }
+
+    while (isspace(UCHAR(*rep)))
+        rep++;
+    if (*rep != '\0')
+        goto err;
+
+    *posPtr = pos;
+    return JIM_OK;
+
+  err:
+    Jim_SetResultFormatted(interp, "expected cursor position but got \"%#s\"", obj);
+    return JIM_ERR;
+}
+
+static int PositionIndex(const MkPosition *posPtr, c4_View view)
+{
+    if (posPtr->endFlag)
+        return view.GetSize() + posPtr->index;
+    else
+        return posPtr->index;
+}
+
+static int JimGetPosition(Jim_Interp *interp, Jim_Obj *obj, c4_View view, int *indexPtr)
+{
+    MkPosition pos;
+
+    if (GetPosition(interp, obj, &pos) != JIM_OK)
+        return JIM_ERR;
+
+    *indexPtr = PositionIndex(&pos, view);
+    return JIM_OK;
+}
+
+/* Cursor type ------------------------------------------------------------- */
+
+typedef struct MkCursor {
+    MkPosition pos;
+    Jim_Obj *viewObj;
+} MkCursor;
+
+#define JimCursorValue(obj) ((MkCursor *)(obj->internalRep.ptr))
+static void FreeCursorInternalRep(Jim_Interp *interp, Jim_Obj *obj)
+{
+    Jim_DecrRefCount(interp, JimCursorValue(obj)->viewObj);
+    Jim_Free(obj->internalRep.ptr);
+}
+
+static void DupCursorInternalRep(Jim_Interp *interp, Jim_Obj *oldObj, Jim_Obj *newObj)
+{
+    newObj->internalRep.ptr = Jim_Alloc(sizeof(MkCursor));
+    *JimCursorValue(newObj) = *JimCursorValue(oldObj);
+    Jim_IncrRefCount(JimCursorValue(oldObj)->viewObj);
+
+    newObj->typePtr = oldObj->typePtr;
+}
+
+static void UpdateStringOfCursor(Jim_Obj *obj)
+{
+    char buf[JIM_CURSOR_SPACE + 1];
+    MkCursor *curPtr = JimCursorValue(obj);
+    int idx, len;
+
+    len = snprintf(buf, JIM_CURSOR_SPACE + 1, "%s!", Jim_String(curPtr->viewObj));
+
+    if (curPtr->pos.endFlag) {
+        idx = curPtr->pos.index + 1;
+        if (idx == 0)
+            len += snprintf(buf + len, JIM_CURSOR_SPACE + 1 - len, "end");
+        else
+            len += snprintf(buf + len, JIM_CURSOR_SPACE + 1 - len, "end%+d", idx);
+    }
+    else {
+        len += snprintf(buf + len, JIM_CURSOR_SPACE + 1 - len, "%d",
+            curPtr->pos.index);
+    }
+
+    obj->bytes = (char *)Jim_Alloc(len + 1);
+    memcpy(obj->bytes, buf, len + 1);
+    obj->length = len;
+}
+
+static Jim_ObjType cursorObjType = {
+    "mk.cursor",
+    FreeCursorInternalRep,
+    DupCursorInternalRep,
+    UpdateStringOfCursor,
+    JIM_TYPE_REFERENCES
+};
+
+static int SetCursorFromAny(Jim_Interp *interp, Jim_Obj *obj)
+{
+    const char *rep, *delim;
+    int len;
+    Jim_Obj *posObj;
+    MkCursor cur;
+
+    rep = Jim_GetString(obj, &len);
+    delim = strrchr(rep, '!');
+
+    if (!delim) {
+        Jim_SetResultFormatted(interp, "expected cursor but got \"%#s\"", obj);
+        return JIM_ERR;
+    }
+
+    cur.viewObj = Jim_NewStringObj(interp, rep, delim - rep);
+    posObj = Jim_NewStringObj(interp, delim + 1, len - (delim - rep) - 1);
+
+    if (GetPosition(interp, posObj, &cur.pos) != JIM_OK) {
+        Jim_FreeNewObj(interp, posObj);
+        Jim_FreeNewObj(interp, cur.viewObj);
+        return JIM_ERR;
+    }
+
+    Jim_FreeIntRep(interp, obj);
+    Jim_FreeNewObj(interp, posObj);
+    Jim_IncrRefCount(cur.viewObj);
+
+    obj->typePtr = &cursorObjType;
+    obj->internalRep.ptr = Jim_Alloc(sizeof(MkCursor));
+    *JimCursorValue(obj) = cur;
+
+    return JIM_OK;
+}
+
+/* Functions --------------------------------------------------------------- */
+
+static int JimCursorPos(Jim_Interp *interp, Jim_Obj *obj, Jim_Obj **posObjPtr)
+{
+    if (obj->typePtr != &cursorObjType && SetCursorFromAny(interp, obj) != JIM_OK)
+        return JIM_ERR;
+
+    *posObjPtr = Jim_NewStringObj(interp, strrchr(Jim_String(obj), '!') + 1, -1);
+    return JIM_OK;
+}
+
+static int JimGetCursorView(Jim_Interp *interp, Jim_Obj *obj, Jim_Obj **viewObjPtr)
+{
+    if (obj->typePtr != &cursorObjType && SetCursorFromAny(interp, obj) != JIM_OK)
+        return JIM_ERR;
+
+    *viewObjPtr = JimCursorValue(obj)->viewObj;
+    return JIM_OK;
+}
+
+static int JimGetCursor(Jim_Interp *interp, Jim_Obj *obj, c4_Cursor *curPtr)
+{
+    c4_View view;
+
+    if (obj->typePtr != &cursorObjType && SetCursorFromAny(interp, obj) != JIM_OK)
+        return JIM_ERR;
+    if (JimGetView(interp, JimCursorValue(obj)->viewObj, &view) != JIM_OK)
+        return JIM_ERR;
+
+    if (curPtr)
+        *curPtr = &view[PositionIndex(&JimCursorValue(obj)->pos, view)];
+    return JIM_OK;
+}
+
+static int JimIncrCursor(Jim_Interp *interp, Jim_Obj *obj, int offset)
+{
+    /* JimPanic((Jim_IsShared(obj), "JimIncrCursor called with shared object")) */
+
+    if (obj->typePtr != &cursorObjType && SetCursorFromAny(interp, obj) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_InvalidateStringRep(obj);
+    JimCursorValue(obj)->pos.index += offset;
+    return JIM_OK;
+}
+
+static int JimSeekCursor(Jim_Interp *interp, Jim_Obj *obj, Jim_Obj *posObj)
+{
+    /* JimPanic((Jim_IsShared(obj), "JimSeekCursor called with shared object")) */
+
+    if (obj->typePtr != &cursorObjType && SetCursorFromAny(interp, obj) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_InvalidateStringRep(obj);
+    return GetPosition(interp, posObj, &JimCursorValue(obj)->pos);
+}
+
+static int JimCheckCursor(Jim_Interp *interp, Jim_Obj *curObj, int flags)
+{
+    static c4_View nullView;
+
+    c4_Cursor cur = &nullView[0];
+    int size;
+
+    if (JimGetCursor(interp, curObj, &cur) != JIM_OK)
+        return JIM_ERR;
+    size = (*cur).Container().GetSize();
+
+    if ((flags & JIM_CURSOR_GET) && (cur._index < 0 || cur._index >= size)) {
+        if (flags & JIM_ERRMSG) {
+            Jim_SetResultFormatted(interp,
+                "cursor \"%#s\" does not point to an existing row", curObj);
+        }
+        return JIM_ERR;
+    }
+    else if ((flags & JIM_CURSOR_SET) && cur._index < 0) {
+        if (flags & JIM_ERRMSG) {
+            Jim_SetResultFormatted(interp,
+                "cursor \"%#s\" points before start of view", curObj);
+        }
+        return JIM_ERR;
+    }
+    else if ((flags & JIM_CURSOR_INSERT) && (cur._index < 0 || cur._index > size)) {
+        if (flags & JIM_ERRMSG) {
+            Jim_SetResultFormatted(interp,
+                "cursor \"%#s\" does not point to a valid insert position", curObj);
+        }
+        return JIM_ERR;
+    }
+
+    return JIM_OK;
+}
+
+/* Records ----------------------------------------------------------------- */
+
+static int cursor_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    c4_View view;
+    c4_Cursor cur = &view[0];
+
+    if (JimGetCursor(interp, argv[0], &cur) != JIM_OK)
+        return JIM_ERR;
+    if (JimCheckCursor(interp, argv[0], JIM_ERRMSG | JIM_CURSOR_GET) != JIM_OK)
+        return JIM_ERR;
+
+    view = (*cur).Container();
+
+    if (argc == 1) { /* Return all properties */
+        int i, count;
+        Jim_Obj *result;
+
+        result = Jim_NewListObj(interp, NULL, 0);
+        count = view.NumProperties();
+
+        for (i = 0; i < count; i++) {
+            c4_Property prop = view.NthProperty(i);
+
+            Jim_ListAppendElement(interp, result, JimNewPropertyObj(interp, prop));
+            Jim_ListAppendElement(interp, result, JimGetMkValue(interp, cur, prop));
+        }
+
+        Jim_SetResult(interp, result);
+        return JIM_OK;
+    }
+    else { /* Return a single property */
+        const c4_Property *propPtr;
+        int pipe;
+
+        pipe = JimPipelineBoundary(argc, argv);
+        if (pipe == 2) {
+            /* No type annotation, existing property */
+            if (JimGetProperty(interp, argv[1], view, NULL, &propPtr) != JIM_OK)
+                return JIM_ERR;
+        }
+        else if (pipe == 3) {
+            /* Explicit type annotation; the property may be new */
+            int idx;
+
+            if (Jim_GetEnum(interp, argv[1], jim_mktype_options, &idx,
+                    "property type", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
+                return JIM_ERR;
+            if (JimGetNewProperty(interp, argv[2], view, jim_mktype_types[idx], &propPtr) != JIM_OK)
+                return JIM_ERR;
+        }
+        else {
+            Jim_WrongNumArgs(interp, 0, NULL, "cursor get ?-type? ?prop?");
+            return JIM_ERR;
+        }
+
+        Jim_SetResult(interp, JimGetMkValue(interp, cur, *propPtr));
+
+        if (pipe == argc)
+            return JIM_OK;
+        else
+            return Jim_EvalObjPrefix(interp, Jim_GetResult(interp), argc - pipe - 1, argv + pipe + 1);
+    }
+}
+
+static int cursor_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    c4_View view;
+    c4_Cursor cur = &view[0];
+    const c4_Property *propPtr;
+    int i, oldSize;
+
+    if (JimGetCursor(interp, argv[0], &cur) != JIM_OK)
+        return JIM_ERR;
+    if (JimCheckCursor(interp, argv[0], JIM_ERRMSG | JIM_CURSOR_SET) != JIM_OK)
+        return JIM_ERR;
+
+    view = (*cur).Container();
+    oldSize = view.GetSize();
+
+    if (cur._index >= oldSize)
+        view.SetSize(cur._index + 1);
+
+    if (argc == 2) {
+        /* Update everything except subviews from a dictionary in argv[1].
+         * No new properties are permitted.
+         */
+
+        int objc;
+        Jim_Obj **objv;
+
+        if (Jim_DictPairs(interp, argv[1], &objv, &objc) != JIM_OK)
+            goto err;
+
+        for (i = 0; i < objc; i += 2) {
+            if (JimGetProperty(interp, objv[i], view, NULL, &propPtr) != JIM_OK ||
+                JimSetMkValue(interp, cur, *propPtr, objv[i+1]) != JIM_OK)
+            {
+                Jim_Free(objv);
+                goto err;
+            }
+        }
+    }
+    else {
+        /* Update everything from argv[1..]. New properties are permitted if
+         * explicitly typed.
+         */
+
+        for (i = 1; i < argc; i += 2) {
+            if (Jim_String(argv[i])[0] == '-') {
+                int idx;
+
+                if (i + 2 >= argc) {
+                    Jim_WrongNumArgs(interp, 2, argv, "?-type? prop value ?...?");
+                    goto err;
+                }
+
+                if (Jim_GetEnum(interp, argv[i], jim_mktype_options, &idx,
+                        "property type", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
+                    goto err;
+                if (JimGetNewProperty(interp, argv[i+1], view, jim_mktype_types[idx], &propPtr) != JIM_OK)
+                    goto err;
+                i++;
+            }
+            else {
+                if (i + 1 >= argc) {
+                    Jim_WrongNumArgs(interp, 2, argv, "?-type? prop value ?...?");
+                    goto err;
+                }
+
+                if (JimGetProperty(interp, argv[i], view, NULL, &propPtr) != JIM_OK)
+                    goto err;
+            }
+
+            if (JimSetMkValue(interp, cur, *propPtr, argv[i+1]) != JIM_OK)
+                goto err;
+        }
+    }
+
+    return JIM_OK;
+
+  err:
+    view.SetSize(oldSize);
+    return JIM_ERR;
+}
+
+static int cursor_cmd_insert(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    c4_View view;
+    c4_Cursor cur = &view[0];
+    jim_wide count;
+
+    if (JimGetCursor(interp, argv[0], &cur) != JIM_OK)
+        return JIM_ERR;
+    if (JimCheckCursor(interp, argv[0], JIM_ERRMSG | JIM_CURSOR_INSERT) != JIM_OK)
+        return JIM_ERR;
+
+    view = (*cur).Container();
+
+    if (argc == 1)
+        count = 1;
+    else {
+        if (Jim_GetWide(interp, argv[1], &count) != JIM_OK)
+            return JIM_ERR;
+    }
+
+    if (count > 0) {
+        c4_Row empty;
+        view.InsertAt(cur._index, empty, (int)count);
+    }
+
+    Jim_SetEmptyResult(interp);
+    return JIM_OK;
+}
+
+static int cursor_cmd_remove(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    c4_View view;
+    c4_Cursor cur = &view[0];
+    int pos;
+    jim_wide count;
+
+    if (JimGetCursor(interp, argv[0], &cur) != JIM_OK)
+        return JIM_ERR;
+    if (JimCheckCursor(interp, argv[0], JIM_ERRMSG | JIM_CURSOR_SET) != JIM_OK)
+        return JIM_ERR;
+
+    view = (*cur).Container();
+    pos = cur._index;
+
+    if (argc == 1)
+        count = 1;
+    else {
+        if (Jim_GetWide(interp, argv[1], &count) != JIM_OK)
+            return JIM_ERR;
+    }
+
+    if (pos + count < view.GetSize())
+        count = view.GetSize() - pos;
+
+    if (pos < view.GetSize())
+        view.RemoveAt(pos, (int)count);
+
+    return JIM_OK;
+}
+
+/* Attributes -------------------------------------------------------------- */
+
+static int cursor_cmd_view(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *viewObj;
+
+    if (JimGetCursorView(interp, argv[0], &viewObj) != JIM_OK)
+        return JIM_ERR;
+
+    JimPinView(interp, viewObj);
+    Jim_SetResult(interp, viewObj);
+    return JIM_OK;
+}
+
+/* Positioning ------------------------------------------------------------- */
+
+static int cursor_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc == 1) {
+        Jim_Obj *result;
+
+        if (JimCursorPos(interp, argv[0], &result) != JIM_OK)
+            return JIM_ERR;
+        Jim_SetResult(interp, result);
+    }
+    else {
+        static c4_View nullView;
+        c4_Cursor cur = &nullView[0];
+
+        if (!Jim_CompareStringImmediate(interp, argv[0], "-absolute")) {
+            Jim_SetResultFormatted(interp,
+                "bad option \"%#s\": must be -absolute", argv[0]);
+            return JIM_ERR;
+        }
+
+        if (JimGetCursor(interp, argv[1], &cur) != JIM_OK)
+            return JIM_ERR;
+
+        Jim_SetResultInt(interp, cur._index);
+    }
+
+    return JIM_OK;
+}
+
+static int cursor_cmd_validfor(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    static const char *options[] = {
+        "get", "set", "insert", "remove", 0
+    };
+    static int optflags[] = {
+        JIM_CURSOR_GET,
+        JIM_CURSOR_SET,
+        JIM_CURSOR_INSERT,
+        JIM_CURSOR_SET
+    };
+
+    int idx;
+
+    if (argc == 1)
+        idx = 0;
+    else {
+        if (Jim_GetEnum(interp, argv[0], options, &idx, NULL,
+                JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
+            return JIM_ERR;
+    }
+
+    if (JimGetCursor(interp, argv[argc-1], NULL) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResultBool(interp, JimCheckCursor(interp, argv[argc-1], optflags[idx]) == JIM_OK);
+    return JIM_OK;
+}
+
+static int cursor_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *curObj;
+
+    curObj = Jim_GetVariable(interp, argv[0], JIM_ERRMSG | JIM_UNSHARED);
+    if (curObj == NULL)
+        return JIM_ERR;
+
+    if (JimSeekCursor(interp, curObj, argv[1]) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, curObj);
+    return JIM_OK;
+}
+
+static int cursor_cmd_incr(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *curObj;
+    jim_wide offset;
+
+    if (argc == 1)
+        offset = 1;
+    else {
+        if (Jim_GetWide(interp, argv[1], &offset) != JIM_OK)
+            return JIM_ERR;
+    }
+
+    curObj = Jim_GetVariable(interp, argv[0], JIM_ERRMSG | JIM_UNSHARED);
+    if (curObj == NULL)
+        return JIM_ERR;
+
+    if (JimIncrCursor(interp, curObj, (int)offset) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, curObj);
+    return JIM_OK;
+}
+
+/* Command table ----------------------------------------------------------- */
+
+static const jim_subcmd_type cursor_command_table[] = {
+
+    /* Records */
+
+    {   "get", "cur ?-type? ?prop?",
+        cursor_cmd_get,
+        1, -1,
+        0,
+        /*"Get the whole record or a specific property at the cursor"*/
+    },
+    {   "set", "cur [dict | ?-type? field value ?...?]",
+        cursor_cmd_set,
+        1, -1,
+        0,
+        /*"Update the record at the cursor"*/
+    },
+    {   "insert", "cur ?count?",
+        cursor_cmd_insert,
+        1, 2,
+        0,
+        /*"Insert a specified number of empty rows at the cursor (default 1)"*/
+    },
+    {   "remove", "cur ?count?",
+        cursor_cmd_remove,
+        1, 2,
+        0,
+        /*"Remove a specified number of rows at the cursor (default 1)"*/
+    },
+
+    /* Attributes */
+
+    {   "view", "cur",
+        cursor_cmd_view,
+        1, 1,
+        0,
+        /*"Get the view the cursor points into"*/
+    },
+
+    /* Positioning */
+
+    {   "tell", "?-absolute? cur",
+        cursor_cmd_tell,
+        1, 2,
+        0,
+        /*"Get the position of the cursor"*/
+    },
+    {   "validfor", "?command? cur",
+        cursor_cmd_validfor,
+        1, 2,
+        0,
+        /*"Checks if the cursor is valid for get (default), set or insert commands"*/
+    },
+    {   "seek", "curVar index",
+        cursor_cmd_seek,
+        2, 2,
+        0,
+        /*"Seek to the specified index in the view"*/
+    },
+    {   "incr", "curVar ?offset?",
+        cursor_cmd_incr,
+        1, 2,
+        0,
+        /*"Move the cursor offset records from its current position (default 1)"*/
+    },
+
+    { 0 }
+};
+
+static int JimCursorCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *cmdObj;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "command ...");
+        return JIM_ERR;
+    }
+
+    cmdObj = Jim_NewStringObj(interp, "cursor ", -1);
+    Jim_AppendObj(interp, cmdObj, argv[1]);
+
+    if (Jim_GetCommand(interp, cmdObj, 0) != NULL)
+        return Jim_EvalObjPrefix(interp, cmdObj, argc - 2, argv + 2);
+    else {
+        Jim_FreeNewObj(interp, cmdObj);
+        return Jim_CallSubCmd(interp,
+            Jim_ParseSubCmd(interp, cursor_command_table, argc, argv), argc, argv);
+    }
+}
+
+/* -------------------------------------------------------------------------
+ * View handle
+ * ------------------------------------------------------------------------- */
+
+/* Views aren't really Jim objects; instead, they are Tk-style commands with
+ * oo.tcl-like lifetime management. Additionally, all views are initially
+ * created as one-shot, meaning that they die after one command. Call
+ * JimPinView to make a view object persistent.
+ *
+ * It is valid to rename a view in the Tcl land, but by doing this you take
+ * the responsibility of destroying the object when it's no longer needed.
+ * Any cursors that pointed into the view become invalid.
+ */
+
+static int JimViewSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+static int JimOneShotViewSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+
+/* Unary operations -------------------------------------------------------- */
+
+#define UNOP(name, Method) \
+static int view_cmd_##name(Jim_Interp *interp, int argc, Jim_Obj *const *argv)  \
+{   \
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);          \
+    \
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->Method()));            \
+    return JIM_OK;                                                              \
+}
+
+UNOP(copy, Duplicate)
+UNOP(clone, Clone)
+UNOP(unique, Unique)
+
+#undef UNOP
+
+static int view_cmd_blocked(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+
+    if (viewPtr->GetSize() != 1 ||
+        strcmp(viewPtr->NthProperty(0).Name(), "_B") != 0 ||
+        viewPtr->NthProperty(0).Type() != MK_PROPERTY_VIEW)
+    {
+        Jim_SetResultString(interp,
+            "blocked view must have exactly one subview property called _B", -1);
+        return JIM_ERR;
+    }
+
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->Blocked()));
+    return JIM_OK;
+}
+
+/* Binary operations ------------------------------------------------------- */
+
+#define BINOP(name, Method) \
+static int view_cmd_##name(Jim_Interp *interp, int argc, Jim_Obj *const *argv)  \
+{   \
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);          \
+    c4_View otherView;                                                          \
+    \
+    if (JimGetView(interp, argv[0], &otherView) != JIM_OK)                      \
+        return JIM_ERR;                                                         \
+    \
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->Method(otherView)));   \
+    return JIM_OK;                                                              \
+}
+
+BINOP(pair, Pair)
+BINOP(concat, Concat)
+BINOP(product, Product)
+
+BINOP(union, Union)
+BINOP(intersect, Intersect)
+BINOP(minus, Minus)
+BINOP(different, Different)
+
+#undef BINOP
+
+/* Projections ------------------------------------------------------------- */
+
+static int view_cmd_project(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    c4_View props;
+
+    if (JimGetProperties(interp, argc, argv, *viewPtr, &props) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->Project(props)));
+    return JIM_OK;
+}
+
+static int view_cmd_without(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    c4_View props;
+
+    if (JimGetProperties(interp, argc, argv, *viewPtr, &props) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->ProjectWithout(props)));
+    return JIM_OK;
+}
+
+static int view_cmd_range(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    int start, end;
+    jim_wide step;
+
+    if (JimGetPosition(interp, argv[0], *viewPtr, &start) != JIM_OK ||
+        JimGetPosition(interp, argv[1], *viewPtr, &end) != JIM_OK)
+    {
+        return JIM_ERR;
+    }
+
+    if (argc == 2)
+        step = 1;
+    else if (Jim_GetWide(interp, argv[2], &step) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->Slice(start, end + 1, (int)step)));
+    return JIM_OK;
+}
+
+/* Ordering ---------------------------------------------------------------- */
+
+static int view_cmd_sort(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    c4_View sortProps, revProps;
+    const c4_Property *propPtr;
+    int i, len;
+
+    const char *rep;
+    int reverse;
+    Jim_Obj *propObj;
+
+    /* Special case: property names may be preceded with a dash. Use
+     * a temporary object in this case.
+     */
+
+    for (i = 0; i < argc; i++) {
+        propObj = argv[i];
+
+        rep = Jim_GetString(argv[i], &len);
+        reverse = (len > 0 && rep[0] == '-');
+
+        if (reverse)
+            propObj = Jim_NewStringObj(interp, rep + 1, len - 1);
+
+        if (JimGetProperty(interp, propObj, *viewPtr, NULL, &propPtr) != JIM_OK) {
+            if (reverse)
+                Jim_FreeNewObj(interp, propObj);
+            return JIM_ERR;
+        }
+
+        sortProps.AddProperty(*propPtr);
+        if (reverse) {
+            revProps.AddProperty(*propPtr);
+            Jim_FreeNewObj(interp, propObj);
+        }
+    }
+
+    if (sortProps.GetSize() == 0)
+        Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->Sort()));
+    else if (revProps.GetSize() == 0)
+        Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->SortOn(sortProps)));
+    else
+        Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->SortOnReverse(sortProps, revProps)));
+
+    return JIM_OK;
+}
+
+/* Metakit core seems to be doing something similar for SortOn, but neither
+ * Ordered nor Hash use it, for unknown reason.
+ */
+
+static int BubbleProperties(Jim_Interp *interp, c4_View orig, int objc, Jim_Obj *const *objv, c4_View *projPtr)
+{
+    c4_View proj;
+    const c4_Property *propPtr;
+    int i, count;
+
+    for (i = 0; i < objc; i++) {
+        if (JimGetProperty(interp, objv[i], orig, NULL, &propPtr) != JIM_OK)
+            return JIM_ERR;
+        proj.AddProperty(*propPtr);
+    }
+
+    count = orig.NumProperties();
+    for (i = 0; i < count; i++)
+        proj.AddProperty(orig.NthProperty(i));
+
+    *projPtr = proj;
+    return JIM_OK;
+}
+
+static int view_cmd_ordered(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    c4_View proj;
+
+    if (BubbleProperties(interp, *viewPtr, argc, argv, &proj) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, JimNewViewObj(interp, proj.Ordered(argc)));
+    return JIM_OK;
+}
+
+static int view_cmd_hash(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    c4_View hash, proj;
+
+    if (JimGetView(interp, argv[0], &hash) != JIM_OK)
+        return JIM_ERR;
+
+    if (hash.GetSize() != 2 ||
+        strcmp(hash.NthProperty(0).Name(), "_H") != 0 ||
+        hash.NthProperty(0).Type() != MK_PROPERTY_INT ||
+        strcmp(hash.NthProperty(1).Name(), "_R") != 0 ||
+        hash.NthProperty(1).Type() != MK_PROPERTY_INT) /* Ouch. */
+    {
+        Jim_SetResultString(interp,
+            "hash view must be laid out as {_H integer _R integer}", -1);
+        return JIM_ERR;
+    }
+
+    if (BubbleProperties(interp, *viewPtr, argc - 1, argv + 1, &proj) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, JimNewViewObj(interp, proj.Hash(hash, argc - 1)));
+    return JIM_OK;
+}
+
+/* Relational operations --------------------------------------------------- */
+
+static int view_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    c4_View other, props;
+    int outer, off;
+
+    if (JimGetView(interp, argv[0], &other) != JIM_OK)
+        return JIM_ERR;
+
+    off = 1; outer = 0;
+    if (Jim_CompareStringImmediate(interp, argv[1], "-outer")) {
+        off++; outer = 1;
+    }
+
+    if (JimGetProperties(interp, argc - off, argv + off, *viewPtr, &props) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->Join(props, other, outer)));
+    return JIM_OK;
+}
+
+static int view_cmd_group(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    const c4_Property *subviewPtr;
+    c4_View props;
+
+    if (JimGetPropertyTyped(interp, argv[0], MK_PROPERTY_VIEW, &subviewPtr) != JIM_OK)
+        return JIM_ERR;
+
+    if (JimGetProperties(interp, argc - 1, argv + 1, *viewPtr, &props) != JIM_OK)
+        return JIM_ERR;
+
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->GroupBy(props, *(c4_ViewProp *)subviewPtr)));
+    return JIM_OK;
+}
+
+static int view_cmd_flatten(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+    const c4_Property *subviewPtr;
+
+    if (JimGetProperty(interp, argv[0], *viewPtr, NULL, &subviewPtr) != JIM_OK)
+        return JIM_ERR;
+
+    if (subviewPtr->Type() != MK_PROPERTY_VIEW) {
+        Jim_SetResultFormatted(interp, "expected a subview property but got %s one",
+            JimMkTypeName(subviewPtr->Type()));
+        return JIM_ERR;
+    }
+
+    Jim_SetResult(interp, JimNewViewObj(interp, viewPtr->JoinProp(*(c4_ViewProp *)subviewPtr)));
+    return JIM_OK;
+}
+
+/* View queries ------------------------------------------------------------ */
+
+static int view_cmd_properties(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *) Jim_CmdPrivData(interp);
+    Jim_SetResult(interp, JimViewPropertiesList(interp, *viewPtr));
+    return JIM_OK;
+}
+
+static int view_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *) Jim_CmdPrivData(interp);
+    Jim_SetResultInt(interp, viewPtr->GetSize());
+    return JIM_OK;
+}
+
+static int view_cmd_resize(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    c4_View *view = (c4_View *) Jim_CmdPrivData(interp);
+    jim_wide size;
+
+    if (Jim_GetWide(interp, argv[0], &size) != JIM_OK)
+        return JIM_ERR;
+    if (size < 0 || size > INT_MAX) {
+        Jim_SetResultFormatted(interp,
+            "view size \"%#s\" is out of range", argv[0]);
+        return JIM_ERR;
+    }
+
+    view->SetSize((int)size);
+    Jim_SetResult(interp, argv[0]);
+    return JIM_OK;
+}
+
+static int view_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    const c4_View *viewPtr = (const c4_View *)Jim_CmdPrivData(interp);
+
+    if (argc == 1) {
+        const c4_Property *propPtr;
+
+        if (JimGetProperty(interp, argv[0], *viewPtr, NULL, &propPtr) != JIM_OK)
+            return JIM_ERR;
+
+        Jim_SetResultString(interp, JimMkTypeName(propPtr->Type()), -1);
+    }
+    else {
+        Jim_Obj *result;
+        int i, count;
+
+        result = Jim_NewListObj(interp, NULL, 0);
+        count = viewPtr->NumProperties();
+
+        for (i = 0; i < count; i++) {
+            c4_Property prop = viewPtr->NthProperty(i);
+            Jim_ListAppendElement(interp, result, JimNewPropertyObj(interp, prop));
+            Jim_ListAppendElement(interp, result,
+                Jim_NewStringObj(interp, JimMkTypeName(prop.Type()), -1));
+        }
+
+        Jim_SetResult(interp, result);
+    }
+
+    return JIM_OK;
+}
+
+/* View lifetime ----------------------------------------------------------- */
+
+static int view_cmd_pin(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    JimPinView(interp, argv[0]);
+    Jim_SetResult(interp, argv[0]);
+    return JIM_OK;
+}
+
+static int view_cmd_as(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    JimPinView(interp, argv[0]);
+    Jim_SetVariable(interp, argv[2], argv[0]);
+    Jim_SetResult(interp, argv[0]);
+    return JIM_OK;
+}
+
+static int view_cmd_destroy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_DeleteCommand(interp, Jim_String(argv[0]));
+    return JIM_OK;
+}
+
+/* Command table ----------------------------------------------------------- */
+
+static const jim_subcmd_type view_command_table[] = {
+
+    /* Unary operations */
+
+    {   "copy", "",
+        view_cmd_copy,
+        0, 0,
+        0,
+        /*"Create a copy of the view with exactly the same data"*/
+    },
+    {   "clone", "",
+        view_cmd_clone,
+        0, 0,
+        0,
+        /*"Create an empty view with the same properties as this one"*/
+    },
+    {   "unique", "",
+        view_cmd_unique,
+        0, 0,
+        0,
+        /*"Derived view without any duplicate rows (read-only, no change notifications)"*/
+    },
+    {   "blocked", "",
+        view_cmd_blocked,
+        0, 0,
+        0,
+        /*"Build a scalable \"blocked\" out of a view with a single subview property called _B"*/
+    },
+
+    /* Binary operations */
+
+    #define BINOP(name, descr)  \
+    {   #name, "otherView",     \
+        view_cmd_##name,        \
+        1, 1, 0,                \
+    }
+
+    BINOP(pair, "Pairwise concatenation of two views"),
+    BINOP(concat, "Concatenation of two views; unlike union, doesn't remove duplicates"),
+    BINOP(product, "Cartesian product of two views, i.e. every row in view paired with every row in otherView"),
+
+    /* Set operations */
+
+    #define SETOP(name, descr) BINOP(name, descr "; works only if all the rows are unique")
+
+    SETOP(union, "Set union of two views (read-only, no change notifications)"),
+    SETOP(intersect, "Set intersection of two views"),
+    SETOP(different, "Symmetric difference of two views"),
+    SETOP(minus, "Set minus, i.e. all rows from view not in otherView"),
+
+    #undef SETOP
+
+    #undef BINOP
+
+    /* Projections and selections */
+
+    {   "project", "prop ?prop ...?",
+        view_cmd_project,
+        1, -1,
+        0,
+        /*"View projection: only the specified properties, in the specified order"*/
+    },
+    {   "without", "prop ?prop ...?",
+        view_cmd_without,
+        1, -1,
+        0,
+        /*"View projection: remove the specified properties"*/
+    },
+    {   "range", "first last ?step?",
+        view_cmd_range,
+        2, 3,
+        0,
+        /*"Range or slice of the view (read-write, no change notifications)"*/
+    },
+
+    /* Ordering */
+
+    {   "sort", "?[prop|-prop] ...?",
+        view_cmd_sort,
+        0, -1,
+        0,
+        /*"Derived view sorted on the specified properties (in order), or on all properties"*/
+    },
+    {   "ordered", "prop ?prop ...?",
+        view_cmd_ordered,
+        1, -1,
+        0,
+        /*"Consider the underlying view ordered on the specified properties"*/
+    },
+    {   "hash", "hashView prop ?prop ...?",
+        view_cmd_hash,
+        2, -1,
+        0,
+        /*"Mapped view maintaining a hash table on the key consisting of the specified properties"*/
+    },
+
+    /* Relational operations */
+
+    {   "join", "view ?-outer? prop ?prop ...?",
+        view_cmd_join,
+        2, -1,
+        0,
+        /*"Relational join with view on the specified properties"*/
+    },
+    {   "group", "subviewName prop ?prop ...?",
+        view_cmd_group,
+        1, -1,
+        0,
+        /*"Group rows with equal specified properties, move all other properties into subview"*/
+    },
+    {   "flatten", "subviewProp",
+        view_cmd_flatten,
+        1, 1,
+        0,
+        /*"Flatten the specified subview; the inverse of group"*/
+    },
+
+    /* Attributes */
+
+    {   "properties", "",
+        view_cmd_properties,
+        0, 0,
+        0,
+        /*"List the properties in this view"*/
+    },
+    {   "size", "",
+        view_cmd_size,
+        0, 0,
+        0,
+        /*"Return the number of records in the view"*/
+    },
+    {   "resize", "newSize",
+        view_cmd_resize,
+        1, 1,
+        0,
+        /*"Set the number of records in the view"*/
+    },
+    {   "type", "?prop?",
+        view_cmd_type,
+        0, 1,
+        0,
+        /*"Return the type of an existing property, or of all properties"*/
+    },
+
+    /* Lifetime management */
+
+    {   "pin", "",
+        view_cmd_pin,
+        0, 0,
+        JIM_MODFLAG_FULLARGV,
+        /*"Marks the view as persistent"*/
+    },
+    {   "as", "varName",
+        view_cmd_as,
+        1, 1,
+        JIM_MODFLAG_FULLARGV,
+        /*"Marks the view as persistent and assigns it to the given variable"*/
+    },
+    {   "destroy", "",
+        view_cmd_destroy,
+        0, 0,
+        JIM_MODFLAG_FULLARGV,
+        /*"Destroys the view explicitly"*/
+    },
+
+    { 0 }
+};
+
+static void JimViewDelProc(Jim_Interp *interp, void *privData)
+{
+    delete (c4_View *)privData;
+}
+
+static int JimViewSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int pipe, result;
+    Jim_Obj *cmdObj;
+
+    pipe = JimPipelineBoundary(argc, argv);
+
+    if (pipe < 1) {
+        Jim_WrongNumArgs(interp, 1, argv, "command ...");
+        return JIM_ERR;
+    }
+
+    /* Check for a Tcl command first, and try builtins afterwards.
+     * We have to do it in this order so that Jim_ParseSubCmd isn't too greedy
+     * about abbreviations, and still it can't now detect ambigous abbrevs
+     * properly :( Tcl commands cannot be abbreviated at all.
+     */
+
+    cmdObj = Jim_NewStringObj(interp, "mk.view ", -1);
+    Jim_AppendObj(interp, cmdObj, argv[1]);
+
+    /* The command will be cached even though we discard the result */
+    if (Jim_GetCommand(interp, cmdObj, 0) != NULL) {
+        /* Shuffle the arguments: $view cmd args... => {mk.view cmd} $view args... */
+
+        Jim_Obj **objv = (Jim_Obj **)Jim_Alloc(pipe * sizeof(Jim_Obj *));
+        objv[0] = cmdObj;
+        objv[1] = argv[0];
+        memcpy(objv + 2, argv + 2, (pipe - 2) * sizeof(Jim_Obj *));
+
+        result = Jim_EvalObjVector(interp, pipe, objv);
+
+        Jim_Free(objv);
+    } else {
+        Jim_FreeNewObj(interp, cmdObj);
+        result = Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, view_command_table, pipe, argv), pipe, argv);
+    }
+
+    if (result != JIM_OK || pipe == argc)
+        return result;
+    else
+        return Jim_EvalObjPrefix(interp, Jim_GetResult(interp), argc - pipe - 1, argv + pipe + 1);
+}
+
+static int JimOneShotViewSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int result;
+    Jim_Cmd *cmd;
+
+    result = JimViewSubCmdProc(interp, argc, argv);
+
+    cmd = Jim_GetCommand(interp, argv[0], 0);
+    if (cmd && !cmd->isproc && cmd->u.native.cmdProc == JimOneShotViewSubCmdProc)
+        Jim_DeleteCommand(interp, Jim_String(argv[0]));
+
+    return result;
+}
+
+static int JimViewFinalizerProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    /* We won't succeed here if the user renamed the command, and this is right */
+    Jim_DeleteCommand(interp, Jim_String(argv[1]));
+    return JIM_OK;
+}
+
+static Jim_Obj *JimNewViewObj(Jim_Interp *interp, c4_View view) {
+    Jim_Obj *tag, *ref;
+
+    tag = Jim_NewStringObj(interp, "mk.view", -1);
+    ref = Jim_NewReference(interp, tag, tag, Jim_NewStringObj(interp, "mk.view.finalizer", -1));
+    Jim_CreateCommand(interp, Jim_String(ref),
+        JimOneShotViewSubCmdProc, new c4_View(view), JimViewDelProc);
+
+    return ref;
+}
+
+static int JimGetView(Jim_Interp *interp, Jim_Obj *obj, c4_View *viewPtr)
+{
+    Jim_Cmd *cmd = Jim_GetCommand(interp, obj, 0);
+
+    if (cmd == NULL || cmd->isproc || cmd->u.native.delProc != JimViewDelProc) {
+        Jim_SetResultFormatted(interp, "invalid view object \"%#s\"", obj);
+        return JIM_ERR;
+    }
+
+    *viewPtr = *(c4_View *)cmd->u.native.privData;
+    return JIM_OK;
+}
+
+/* Only call this against known view objects. */
+static void JimPinView(Jim_Interp *interp, Jim_Obj *obj)
+{
+    Jim_Cmd *cmd = Jim_GetCommand(interp, obj, 0);
+    /* JimPanic((cmd == NULL, "JimPinView called against non-view"))
+       JimPanic((cmd->u.native.delProc != JimViewDelProc, "JimPinView called against non-view")) */
+    cmd->u.native.cmdProc = JimViewSubCmdProc;
+}
+
+static Jim_Obj *JimViewPropertiesList(Jim_Interp *interp, c4_View view)
+{
+    int i, count;
+    Jim_Obj *result;
+
+    result = Jim_NewListObj(interp, NULL, 0);
+    count = view.NumProperties();
+
+    for (i = 0; i < count; i++) {
+        Jim_ListAppendElement(interp, result, Jim_NewStringObj(interp,
+            view.NthProperty(i).Name(), -1));
+    }
+
+    return result;
+}
+
+/* ----------------------------------------------------------------------------
+ * Storage handle
+ * ---------------------------------------------------------------------------- */
+
+/* These are also commands, like views, but must be managed explicitly by the
+ * user. Quite like file handles, actually.
+ */
+
+typedef struct MkStorage {
+    unsigned flags;
+    Jim_Obj *filename;
+    c4_Storage storage;
+    c4_Cursor content;
+} MkStorage;
+
+#define JIM_MKFLAG_INMEMORY     0x0001
+#define JIM_MKFLAG_READONLY     0x0002
+#define JIM_MKFLAG_EXTEND       0x0004
+#define JIM_MKFLAG_AUTOCOMMIT   0x0008
+
+/* Attributes -------------------------------------------------------------- */
+
+static int storage_cmd_autocommit(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk = (MkStorage *)Jim_CmdPrivData(interp);
+
+    if (argc == 1) {
+        jim_wide flag;
+
+        if (Jim_GetWide(interp, argv[0], &flag) != JIM_OK)
+            return JIM_ERR;
+
+        if (flag)
+            mk->flags |= JIM_MKFLAG_AUTOCOMMIT;
+        else
+            mk->flags &= ~JIM_MKFLAG_AUTOCOMMIT;
+        mk->storage.AutoCommit(flag);
+    }
+
+    Jim_SetResultBool(interp, (mk->flags & JIM_MKFLAG_AUTOCOMMIT) != 0);
+    return JIM_OK;
+}
+
+static int storage_cmd_readonly(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk = (MkStorage *)Jim_CmdPrivData(interp);
+
+    Jim_SetResultBool(interp, (mk->flags & JIM_MKFLAG_READONLY) != 0);
+    return JIM_OK;
+}
+
+/* Views ------------------------------------------------------------------- */
+
+static int storage_cmd_views(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk = (MkStorage *)Jim_CmdPrivData(interp);
+
+    Jim_SetResult(interp, JimViewPropertiesList(interp, mk->storage));
+    return JIM_OK;
+}
+
+static int storage_cmd_view(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk = (MkStorage *)Jim_CmdPrivData(interp);
+    const c4_Property *propPtr;
+
+    if (JimGetProperty(interp, argv[0], mk->storage, "view", &propPtr) != JIM_OK)
+        return JIM_ERR;
+    Jim_SetResult(interp, JimGetMkValue(interp, mk->content, *propPtr));
+
+    if (argc == 1)
+        return JIM_OK;
+    else {
+        if (!Jim_CompareStringImmediate(interp, argv[1], "|")) {
+            Jim_SetResultFormatted(interp,
+                "expected start of a pipeline but got \"%#s\"", argv[1]);
+            return JIM_ERR;
+        }
+        return Jim_EvalObjPrefix(interp, Jim_GetResult(interp), argc - 2, argv + 2);
+    }
+}
+
+static int storage_cmd_structure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk = (MkStorage *)Jim_CmdPrivData(interp);
+
+    if (argc < 2) { /* Query */
+        const char *name;
+
+        if (argc == 0)
+            name = NULL;
+        else {
+            const c4_Property *propPtr;
+
+            if (JimGetProperty(interp, argv[0], mk->storage, "view", &propPtr) != JIM_OK)
+                return JIM_ERR;
+            name = propPtr->Name();
+        }
+
+        Jim_SetResult(interp, JimFromMkDescription(interp,
+            mk->storage.Description(name), NULL));
+    }
+    else { /* Modify */
+        char *descr;
+        const char *name;
+        int len, dlen;
+
+        if (JimCheckMkName(interp, argv[0], "view") != JIM_OK)
+            return JIM_ERR;
+        name = Jim_GetString(argv[0], &len);
+
+        if (JimToMkDescription(interp, argv[1], &descr) != JIM_OK)
+            return JIM_ERR;
+        dlen = strlen(descr);
+
+        descr = (char *)Jim_Realloc(descr, dlen + len + 2);
+        memmove(descr + len + 1, descr, dlen);
+        memcpy(descr, name, len);
+        descr[len] = '[';
+        descr[len + 1 + dlen] = ']';
+        descr[len + 1 + dlen + 1] = '\0';
+
+        mk->storage.GetAs(descr);
+
+        Jim_Free(descr);
+    }
+
+    return JIM_OK;
+}
+
+/* Store operations -------------------------------------------------------- */
+
+static int storage_cmd_commit(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk = (MkStorage *)Jim_CmdPrivData(interp);
+
+    if (mk->flags & JIM_MKFLAG_INMEMORY) {
+        Jim_SetResultString(interp, "cannot commit an in-memory storage", -1);
+        return JIM_ERR;
+    }
+    else if (mk->flags & JIM_MKFLAG_READONLY) {
+        Jim_SetResultString(interp, "cannot commit a read-only storage", -1);
+        return JIM_ERR;
+    }
+
+    if (mk->storage.Commit(0)) {
+        Jim_SetEmptyResult(interp);
+        return JIM_OK;
+    }
+    else {
+        Jim_SetResultString(interp, "I/O error during commit", -1);
+        return JIM_ERR;
+    }
+}
+
+static int storage_cmd_rollback(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk = (MkStorage *)Jim_CmdPrivData(interp);
+
+    if (mk->flags & JIM_MKFLAG_INMEMORY) {
+        Jim_SetResultString(interp, "cannot rollback an in-memory storage", -1);
+        return JIM_ERR;
+    }
+
+    if (mk->storage.Rollback(0)) {
+        Jim_SetEmptyResult(interp);
+        return JIM_OK;
+    }
+    else {
+        Jim_SetResultString(interp, "I/O error during rollback", -1);
+        return JIM_ERR;
+    }
+}
+
+static int storage_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    return Jim_DeleteCommand(interp, Jim_String(argv[0]));
+}
+
+/* Command table ----------------------------------------------------------- */
+
+static const jim_subcmd_type storage_command_table[] = {
+
+    /* Options */
+
+    {   "autocommit", "?value?",
+        storage_cmd_autocommit,
+        0, 1,
+        0,
+        /*"Query or modify the auto-commit option of this storage"*/
+    },
+    {   "readonly", "",
+        storage_cmd_readonly,
+        0, 0,
+        0,
+        /*"Returns the read-only status of this storage"*/
+    },
+
+    /* Views */
+
+    {   "views", "",
+        storage_cmd_views,
+        0, 0,
+        0,
+        /*"Returns the list of views stored here"*/
+    },
+    {   "view", "viewName",
+        storage_cmd_view,
+        1, -1,
+        0,
+        /*"Retrieve the view specified by viewName"*/
+    },
+    {   "structure", "?viewName? ?description?",
+        storage_cmd_structure,
+        0, 2,
+        0,
+        /*"Query or modify the structure of this storage"*/
+    },
+
+    /* Store operations */
+
+    {   "commit", "",
+        storage_cmd_commit,
+        0, 0,
+        0,
+        /*"Commit the changes to disk"*/
+    },
+    {   "rollback", "",
+        storage_cmd_rollback,
+        0, 0,
+        0,
+        /*"Revert to the saved state"*/
+    },
+    {   "close", "",
+        storage_cmd_close,
+        0, 0,
+        JIM_MODFLAG_FULLARGV,
+        /*"Close this storage"*/
+    },
+
+    { 0 }
+};
+
+static void JimStorageDelProc(Jim_Interp *interp, void *privData)
+{
+    MkStorage *mk = (MkStorage *)privData;
+
+    mk->storage.~c4_Storage();
+    mk->content.~c4_Cursor();
+    Jim_DecrRefCount(interp, mk->filename);
+    Jim_Free(mk);
+}
+
+static int JimStorageSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *cmdObj;
+
+    cmdObj = Jim_NewStringObj(interp, "mk.storage ", -1);
+    Jim_AppendObj(interp, cmdObj, argv[1]);
+
+    if (Jim_GetCommand(interp, cmdObj, 0) != NULL) {
+        int result;
+
+        Jim_Obj **objv = (Jim_Obj **)Jim_Alloc(argc * sizeof(Jim_Obj *));
+        objv[0] = cmdObj;
+        objv[1] = argv[0];
+        memcpy(objv + 2, argv + 2, (argc - 2) * sizeof(Jim_Obj *));
+
+        result = Jim_EvalObjVector(interp, argc, objv);
+
+        Jim_Free(objv);
+        return result;
+    } else {
+        Jim_FreeNewObj(interp, cmdObj);
+        return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp,
+            storage_command_table, argc, argv), argc, argv);
+    }
+}
+
+/* -------------------------------------------------------------------------
+ * storage ?options? ?filename?
+ *
+ * Creates a new metakit storage object, optionally backed by a file.
+ *
+ * Options apply only when filename is given; these include:
+ *
+ *   -readonly   Open the file in read-only mode
+ *   -original   Open the file in read-only mode, discarding possible extends
+ *   -extend     Open the file in extend mode
+ *   -nocommit   Do not commit the changes when the storage is closed
+ * ------------------------------------------------------------------------- */
+
+static int JimStorageCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    MkStorage *mk;
+    char buf[MK_CMD_LEN];
+    int i, mode;
+
+    static const char *const options[] = {
+        "-readonly",
+        "-original",
+        "-extend",
+        "-nocommit",
+        0
+    };
+    enum {
+        OPT_READONLY,
+        OPT_ORIGINAL,
+        OPT_EXTEND,
+        OPT_NOCOMMIT
+    };
+    int option;
+
+    mk = (MkStorage *)Jim_Alloc(sizeof(MkStorage));
+    mk->flags = JIM_MKFLAG_AUTOCOMMIT;
+    mode = MK_MODE_READWRITE;
+    for (i = 1; i < argc - 1; i++ ) {
+        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
+            Jim_Free(mk);
+            return JIM_ERR;
+        }
+
+        switch (option) {
+            case OPT_READONLY:
+                if (mode != MK_MODE_READWRITE)
+                    goto modeconflict;
+
+                mode = MK_MODE_READONLY;
+                mk->flags |= JIM_MKFLAG_READONLY;
+                break;
+
+            case OPT_ORIGINAL:
+                if (mode != MK_MODE_READWRITE)
+                    goto modeconflict;
+
+                mode = MK_MODE_ORIGINAL;
+                mk->flags |= JIM_MKFLAG_READONLY;
+                break;
+
+            case OPT_EXTEND:
+                if (mode != MK_MODE_READWRITE)
+                    goto modeconflict;
+
+                mode = MK_MODE_EXTEND;
+                mk->flags |= JIM_MKFLAG_EXTEND;
+                break;
+
+            case OPT_NOCOMMIT:
+                mk->flags &= ~JIM_MKFLAG_AUTOCOMMIT;
+                break;
+        }
+    }
+
+    if (argc > 1) {
+        new(&mk->storage) c4_Storage(Jim_String(argv[argc-1]), mode);
+
+        if (!mk->storage.Strategy().IsValid()) {
+            mk->storage.~c4_Storage();
+            Jim_Free(mk);
+            Jim_SetResultFormatted(interp, "could not open storage \"%#s\"", argv[argc-1]);
+            return JIM_ERR;
+        }
+
+        mk->filename = argv[argc-1];
+
+        if ((mk->flags & JIM_MKFLAG_AUTOCOMMIT) && !(mk->flags & JIM_MKFLAG_READONLY))
+            mk->storage.AutoCommit(1);
+    }
+    else {
+        mk->flags |= JIM_MKFLAG_INMEMORY;
+
+        new(&mk->storage) c4_Storage();
+        mk->filename = Jim_NewEmptyStringObj(interp);
+    }
+    new(&mk->content) c4_Cursor(&mk->storage[0]);
+    Jim_IncrRefCount(mk->filename);
+
+    snprintf(buf, sizeof(buf), "mk.handle%ld", Jim_GetId(interp));
+    Jim_CreateCommand(interp, buf, JimStorageSubCmdProc, mk, JimStorageDelProc);
+    Jim_SetResultString(interp, buf, -1);
+    return JIM_OK;
+
+  modeconflict:
+    Jim_Free(mk);
+    Jim_SetResultString(interp, "only one of -readonly, -original and -extend may be specified", -1);
+    return JIM_ERR;
+}
+
+/* -------------------------------------------------------------------------
+ * Initialization code
+ * ------------------------------------------------------------------------- */
+
+int Jim_mkInit(Jim_Interp *interp)
+{
+    char version[MK_VERSION_SPACE];
+
+    snprintf(version, MK_VERSION_SPACE, "%d.%d.%d",
+        d4_MetakitLibraryVersion / 100,
+        d4_MetakitLibraryVersion % 100 / 10,
+        d4_MetakitLibraryVersion % 10);
+
+    if (Jim_PackageProvide(interp, "mk", version, JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "storage", JimStorageCommand, NULL, NULL);
+    Jim_CreateCommand(interp, "cursor", JimCursorCommand, NULL, NULL);
+    Jim_CreateCommand(interp, "mk.view.finalizer", JimViewFinalizerProc, NULL, NULL);
+
+    return JIM_OK;
+}
+
+} /* extern "C" */
diff --git a/jim/jim-namespace.c b/jim/jim-namespace.c
new file mode 100644 (file)
index 0000000..600f8ec
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Support for namespaces in jim
+ *
+ * (c) 2011 Steve Bennett <steveb@workware.net.au>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
+ *
+ * Based on code originally from Tcl 6.7:
+ *
+ * Copyright 1987-1991 Regents of the University of California
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies.  The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "jim.h"
+#include "jimautoconf.h"
+#include "jim-subcmd.h"
+
+/* -----------------------------------------------------------------------------
+ * Namespace support
+ * ---------------------------------------------------------------------------*/
+
+/**
+ * nsObj is a canonical namespace name (.e.g. "" for root, "abc" for ::abc)
+ *
+ * The given name is appended to the namespace name to produce a complete canonical name.
+ *
+ * e.g. "" "abc"         => abc
+ *      "" "::abc"       => abc
+ *      "" "abc::def"    => abc::def
+ *      "abc" "def"      => abc::def
+ *      "abc" "::def"    => def
+ *
+ */
+Jim_Obj *JimCanonicalNamespace(Jim_Interp *interp, Jim_Obj *nsObj, Jim_Obj *nameObj)
+{
+    Jim_Obj *objPtr;
+    const char *name = Jim_String(nameObj);
+    assert(nameObj->refCount != 0);
+    assert(nsObj->refCount != 0);
+    if (name[0] == ':' && name[1] == ':') {
+        /* Absolute namespace */
+        while (*++name == ':') {
+        }
+        return Jim_NewStringObj(interp, name, -1);
+    }
+    if (Jim_Length(nsObj) == 0) {
+        /* Relative to the global namespace */
+        return nameObj;
+    }
+    /* Relative to non-global namespace */
+    objPtr = Jim_DuplicateObj(interp, nsObj);
+    Jim_AppendString(interp, objPtr, "::", 2);
+    Jim_AppendObj(interp, objPtr, nameObj);
+    return objPtr;
+}
+
+int Jim_CreateNamespaceVariable(Jim_Interp *interp, Jim_Obj *varNameObj, Jim_Obj *targetNameObj)
+{
+    int rc;
+    Jim_IncrRefCount(varNameObj);
+    Jim_IncrRefCount(targetNameObj);
+
+    /* push non-namespace vars if in namespace eval? */
+    rc  = Jim_SetVariableLink(interp, varNameObj, targetNameObj, interp->topFramePtr);
+    if (rc == JIM_ERR) {
+        /* This is the only reason the link can fail */
+        Jim_SetResultFormatted(interp, "can't define \"%#s\": name refers to an element in an array", varNameObj);
+    }
+
+    Jim_DecrRefCount(interp, varNameObj);
+    Jim_DecrRefCount(interp, targetNameObj);
+
+    return rc;
+}
+
+/**
+ * Returns the parent of the given namespace.
+ *
+ * ::bob::tom => ::bob
+ * bob::tom   => bob
+ * ::bob      => ::
+ * bob        => ""
+ * ::         => ""
+ * ""         => ""
+ */
+Jim_Obj *Jim_NamespaceQualifiers(Jim_Interp *interp, Jim_Obj *ns)
+{
+    const char *name = Jim_String(ns);
+    const char *pt = strrchr(name, ':');
+    if (pt && pt != name && pt[-1] == ':') {
+        return Jim_NewStringObj(interp, name, pt - name - 1);
+    }
+    else {
+        return interp->emptyObj;
+    }
+}
+
+Jim_Obj *Jim_NamespaceTail(Jim_Interp *interp, Jim_Obj *ns)
+{
+    const char *name = Jim_String(ns);
+    const char *pt = strrchr(name, ':');
+    if (pt && pt != name && pt[-1] == ':') {
+        return Jim_NewStringObj(interp, pt + 1, -1);
+    }
+    else {
+        return ns;
+    }
+}
+
+static Jim_Obj *JimNamespaceCurrent(Jim_Interp *interp)
+{
+    Jim_Obj *objPtr = Jim_NewStringObj(interp, "::", 2);
+    Jim_AppendObj(interp, objPtr, interp->framePtr->nsObj);
+    return objPtr;
+}
+
+static int JimVariableCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int retcode = JIM_OK;
+
+    if (argc > 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "name ?value?");
+        return JIM_ERR;
+    }
+    if (argc > 1) {
+        Jim_Obj *targetNameObj;
+        Jim_Obj *localNameObj;
+
+        targetNameObj = JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[1]);
+
+        localNameObj = Jim_NamespaceTail(interp, argv[1]);
+        Jim_IncrRefCount(localNameObj);
+        if (interp->framePtr->level != 0 || Jim_Length(interp->framePtr->nsObj) != 0) {
+            retcode = Jim_CreateNamespaceVariable(interp, localNameObj, targetNameObj);
+        }
+
+        /* Set the variable via the local name */
+        if (retcode == JIM_OK && argc > 2) {
+            retcode = Jim_SetVariable(interp, localNameObj, argv[2]);
+        }
+        Jim_DecrRefCount(interp, localNameObj);
+    }
+    return retcode;
+}
+
+/* Used to invoke script-based helpers.
+ * It would be ideal if ensembles were supported in the core
+ */
+static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1);
+
+    Jim_AppendString(interp, prefixObj, " ", 1);
+    Jim_AppendString(interp, prefixObj, subcmd, -1);
+
+    return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
+}
+
+static int JimNamespaceCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *nsObj;
+    Jim_Obj *objPtr;
+    int option;
+    static const char * const options[] = {
+        "eval", "current", "canonical", "qualifiers", "parent", "tail", "delete",
+        "origin", "code", "inscope", "import", "export",
+        "which", "upvar", NULL
+    };
+    enum
+    {
+        OPT_EVAL, OPT_CURRENT, OPT_CANONICAL, OPT_QUALIFIERS, OPT_PARENT, OPT_TAIL, OPT_DELETE,
+        OPT_ORIGIN, OPT_CODE, OPT_INSCOPE, OPT_IMPORT, OPT_EXPORT,
+        OPT_WHICH, OPT_UPVAR,
+    };
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arg ...?");
+        return JIM_ERR;
+    }
+
+    if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    switch (option) {
+        case OPT_EVAL:
+            if (argc < 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "name arg ?arg...?");
+                return JIM_ERR;
+            }
+            if (argc == 4) {
+                objPtr = argv[3];
+            }
+            else {
+                objPtr = Jim_ConcatObj(interp, argc - 3, argv + 3);
+            }
+
+            nsObj = JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[2]);
+            return Jim_EvalNamespace(interp, objPtr, nsObj);
+
+        case OPT_CURRENT:
+            if (argc != 2) {
+                Jim_WrongNumArgs(interp, 2, argv, "");
+                return JIM_ERR;
+            }
+            Jim_SetResult(interp, JimNamespaceCurrent(interp));
+            return JIM_OK;
+
+        case OPT_CANONICAL:
+            if (argc > 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "?current? ?name?");
+                return JIM_ERR;
+            }
+            if (argc == 2) {
+                Jim_SetResult(interp, interp->framePtr->nsObj);
+            }
+            else if (argc == 3) {
+                Jim_SetResult(interp, JimCanonicalNamespace(interp, interp->framePtr->nsObj, argv[2]));
+            }
+            else {
+                Jim_SetResult(interp, JimCanonicalNamespace(interp, argv[2], argv[3]));
+            }
+            return JIM_OK;
+
+        case OPT_QUALIFIERS:
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "string");
+                return JIM_ERR;
+            }
+            Jim_SetResult(interp, Jim_NamespaceQualifiers(interp, argv[2]));
+            return JIM_OK;
+
+        case OPT_IMPORT:
+        case OPT_EXPORT:
+            return JIM_OK;
+
+        case OPT_TAIL:
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "string");
+                return JIM_ERR;
+            }
+            Jim_SetResult(interp, Jim_NamespaceTail(interp, argv[2]));
+            return JIM_OK;
+
+        case OPT_PARENT:
+            if (argc != 2 && argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "?name?");
+                return JIM_ERR;
+            }
+            else {
+                const char *name;
+
+                if (argc == 3) {
+                    objPtr = argv[2];
+                }
+                else {
+                    objPtr = interp->framePtr->nsObj;
+                }
+                if (Jim_Length(objPtr) == 0 || Jim_CompareStringImmediate(interp, objPtr, "::")) {
+                    return JIM_OK;
+                }
+                objPtr = Jim_NamespaceQualifiers(interp, objPtr);
+
+                name = Jim_String(objPtr);
+
+                if (name[0] != ':' || name[1] != ':') {
+                    /* Make it fully scoped */
+                    Jim_SetResultString(interp, "::", 2);
+                    Jim_AppendObj(interp, Jim_GetResult(interp), objPtr);
+                    Jim_IncrRefCount(objPtr);
+                    Jim_DecrRefCount(interp, objPtr);
+                }
+                else {
+                    Jim_SetResult(interp, objPtr);
+                }
+            }
+            return JIM_OK;
+    }
+
+    /* Implemented as a Tcl helper proc.
+     * Note that calling a proc will change the current namespace,
+     * so helper procs must call [uplevel namespace canon] to get the callers
+     * namespace.
+     */
+    return Jim_EvalEnsemble(interp, "namespace", options[option], argc - 2, argv + 2);
+}
+
+int Jim_namespaceInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "namespace", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "namespace", JimNamespaceCmd, NULL, NULL);
+    Jim_CreateCommand(interp, "variable", JimVariableCmd, NULL, NULL);
+    return JIM_OK;
+}
+
diff --git a/jim/jim-nvp.c b/jim/jim-nvp.c
deleted file mode 100644 (file)
index be94f15..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-#include <string.h>
-#include <jim-nvp.h>
-
-int Jim_GetNvp(Jim_Interp *interp,
-    Jim_Obj *objPtr, const Jim_Nvp * nvp_table, const Jim_Nvp ** result)
-{
-    Jim_Nvp *n;
-    int e;
-
-    e = Jim_Nvp_name2value_obj(interp, nvp_table, objPtr, &n);
-    if (e == JIM_ERR) {
-        return e;
-    }
-
-    /* Success? found? */
-    if (n->name) {
-        /* remove const */
-        *result = (Jim_Nvp *) n;
-        return JIM_OK;
-    }
-    else {
-        return JIM_ERR;
-    }
-}
-
-Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp * p, const char *name)
-{
-    while (p->name) {
-        if (0 == strcmp(name, p->name)) {
-            break;
-        }
-        p++;
-    }
-    return ((Jim_Nvp *) (p));
-}
-
-Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp * p, const char *name)
-{
-    while (p->name) {
-        if (0 == strcasecmp(name, p->name)) {
-            break;
-        }
-        p++;
-    }
-    return ((Jim_Nvp *) (p));
-}
-
-int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** result)
-{
-    return Jim_Nvp_name2value(interp, p, Jim_String(o), result);
-}
-
-
-int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp * _p, const char *name, Jim_Nvp ** result)
-{
-    const Jim_Nvp *p;
-
-    p = Jim_Nvp_name2value_simple(_p, name);
-
-    /* result */
-    if (result) {
-        *result = (Jim_Nvp *) (p);
-    }
-
-    /* found? */
-    if (p->name) {
-        return JIM_OK;
-    }
-    else {
-        return JIM_ERR;
-    }
-}
-
-int
-Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** puthere)
-{
-    return Jim_Nvp_name2value_nocase(interp, p, Jim_String(o), puthere);
-}
-
-int
-Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp * _p, const char *name,
-    Jim_Nvp ** puthere)
-{
-    const Jim_Nvp *p;
-
-    p = Jim_Nvp_name2value_nocase_simple(_p, name);
-
-    if (puthere) {
-        *puthere = (Jim_Nvp *) (p);
-    }
-    /* found */
-    if (p->name) {
-        return JIM_OK;
-    }
-    else {
-        return JIM_ERR;
-    }
-}
-
-
-int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** result)
-{
-    int e;;
-    jim_wide w;
-
-    e = Jim_GetWide(interp, o, &w);
-    if (e != JIM_OK) {
-        return e;
-    }
-
-    return Jim_Nvp_value2name(interp, p, w, result);
-}
-
-Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp * p, int value)
-{
-    while (p->name) {
-        if (value == p->value) {
-            break;
-        }
-        p++;
-    }
-    return ((Jim_Nvp *) (p));
-}
-
-
-int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp * _p, int value, Jim_Nvp ** result)
-{
-    const Jim_Nvp *p;
-
-    p = Jim_Nvp_value2name_simple(_p, value);
-
-    if (result) {
-        *result = (Jim_Nvp *) (p);
-    }
-
-    if (p->name) {
-        return JIM_OK;
-    }
-    else {
-        return JIM_ERR;
-    }
-}
-
-
-int Jim_GetOpt_Setup(Jim_GetOptInfo * p, Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-    memset(p, 0, sizeof(*p));
-    p->interp = interp;
-    p->argc = argc;
-    p->argv = argv;
-
-    return JIM_OK;
-}
-
-void Jim_GetOpt_Debug(Jim_GetOptInfo * p)
-{
-    int x;
-
-    fprintf(stderr, "---args---\n");
-    for (x = 0; x < p->argc; x++) {
-        fprintf(stderr, "%2d) %s\n", x, Jim_String(p->argv[x]));
-    }
-    fprintf(stderr, "-------\n");
-}
-
-
-int Jim_GetOpt_Obj(Jim_GetOptInfo * goi, Jim_Obj **puthere)
-{
-    Jim_Obj *o;
-
-    o = NULL;                   // failure
-    if (goi->argc) {
-        // success
-        o = goi->argv[0];
-        goi->argc -= 1;
-        goi->argv += 1;
-    }
-    if (puthere) {
-        *puthere = o;
-    }
-    if (o != NULL) {
-        return JIM_OK;
-    }
-    else {
-        return JIM_ERR;
-    }
-}
-
-int Jim_GetOpt_String(Jim_GetOptInfo * goi, char **puthere, int *len)
-{
-    int r;
-    Jim_Obj *o;
-    const char *cp;
-
-
-    r = Jim_GetOpt_Obj(goi, &o);
-    if (r == JIM_OK) {
-        cp = Jim_GetString(o, len);
-        if (puthere) {
-            /* remove const */
-            *puthere = (char *)(cp);
-        }
-    }
-    return r;
-}
-
-int Jim_GetOpt_Double(Jim_GetOptInfo * goi, double *puthere)
-{
-    int r;
-    Jim_Obj *o;
-    double _safe;
-
-    if (puthere == NULL) {
-        puthere = &_safe;
-    }
-
-    r = Jim_GetOpt_Obj(goi, &o);
-    if (r == JIM_OK) {
-        r = Jim_GetDouble(goi->interp, o, puthere);
-        if (r != JIM_OK) {
-            Jim_SetResultFormatted(goi->interp, "not a number: %#s", o);
-        }
-    }
-    return r;
-}
-
-int Jim_GetOpt_Wide(Jim_GetOptInfo * goi, jim_wide * puthere)
-{
-    int r;
-    Jim_Obj *o;
-    jim_wide _safe;
-
-    if (puthere == NULL) {
-        puthere = &_safe;
-    }
-
-    r = Jim_GetOpt_Obj(goi, &o);
-    if (r == JIM_OK) {
-        r = Jim_GetWide(goi->interp, o, puthere);
-    }
-    return r;
-}
-
-int Jim_GetOpt_Nvp(Jim_GetOptInfo * goi, const Jim_Nvp * nvp, Jim_Nvp ** puthere)
-{
-    Jim_Nvp *_safe;
-    Jim_Obj *o;
-    int e;
-
-    if (puthere == NULL) {
-        puthere = &_safe;
-    }
-
-    e = Jim_GetOpt_Obj(goi, &o);
-    if (e == JIM_OK) {
-        e = Jim_Nvp_name2value_obj(goi->interp, nvp, o, puthere);
-    }
-
-    return e;
-}
-
-void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo * goi, const Jim_Nvp * nvptable, int hadprefix)
-{
-    if (hadprefix) {
-        Jim_SetResult_NvpUnknown(goi->interp, goi->argv[-2], goi->argv[-1], nvptable);
-    }
-    else {
-        Jim_SetResult_NvpUnknown(goi->interp, NULL, goi->argv[-1], nvptable);
-    }
-}
-
-
-int Jim_GetOpt_Enum(Jim_GetOptInfo * goi, const char *const *lookup, int *puthere)
-{
-    int _safe;
-    Jim_Obj *o;
-    int e;
-
-    if (puthere == NULL) {
-        puthere = &_safe;
-    }
-    e = Jim_GetOpt_Obj(goi, &o);
-    if (e == JIM_OK) {
-        e = Jim_GetEnum(goi->interp, o, lookup, puthere, "option", JIM_ERRMSG);
-    }
-    return e;
-}
-
-void
-Jim_SetResult_NvpUnknown(Jim_Interp *interp,
-    Jim_Obj *param_name, Jim_Obj *param_value, const Jim_Nvp * nvp)
-{
-    if (param_name) {
-        Jim_SetResultFormatted(interp, "%#s: Unknown: %#s, try one of: ", param_name, param_value);
-    }
-    else {
-        Jim_SetResultFormatted(interp, "Unknown param: %#s, try one of: ", param_value);
-    }
-    while (nvp->name) {
-        const char *a;
-        const char *b;
-
-        if ((nvp + 1)->name) {
-            a = nvp->name;
-            b = ", ";
-        }
-        else {
-            a = "or ";
-            b = nvp->name;
-        }
-        Jim_AppendStrings(interp, Jim_GetResult(interp), a, b, NULL);
-        nvp++;
-    }
-}
-
-const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-    static Jim_Obj *debug_string_obj;
-
-    int x;
-
-    if (debug_string_obj) {
-        Jim_FreeObj(interp, debug_string_obj);
-    }
-
-    debug_string_obj = Jim_NewEmptyStringObj(interp);
-    for (x = 0; x < argc; x++) {
-        Jim_AppendStrings(interp, debug_string_obj, Jim_String(argv[x]), " ", NULL);
-    }
-
-    return Jim_String(debug_string_obj);
-}
-
-int Jim_nvpInit(Jim_Interp *interp)
-{
-    /* This is really a helper library, not an extension, but this is the easy way */
-    return JIM_OK;
-}
diff --git a/jim/jim-nvp.h b/jim/jim-nvp.h
deleted file mode 100644 (file)
index 12ff889..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-#ifndef JIM_NVP_H
-#define JIM_NVP_H
-
-#include <jim.h>
-
-/** Name Value Pairs, aka: NVP
- *   -  Given a string - return the associated int.
- *   -  Given a number - return the associated string.
- *   .
- *
- * Very useful when the number is not a simple index into an array of
- * known string, or there may be multiple strings (aliases) that mean then same
- * thing.
- *
- * An NVP Table is terminated with ".name = NULL".
- *
- * During the 'name2value' operation, if no matching string is found
- * the pointer to the terminal element (with p->name == NULL) is returned.
- *
- * Example:
- * \code
- *      const Jim_Nvp yn[] = {
- *          { "yes", 1 },
- *          { "no" , 0 },
- *          { "yep", 1 },
- *          { "nope", 0 },
- *          { NULL, -1 },
- *      };
- *
- *  Jim_Nvp *result
- *  e = Jim_Nvp_name2value(interp, yn, "y", &result);
- *         returns &yn[0];
- *  e = Jim_Nvp_name2value(interp, yn, "n", &result);
- *         returns &yn[1];
- *  e = Jim_Nvp_name2value(interp, yn, "Blah", &result);
- *         returns &yn[4];
- * \endcode
- *
- * During the number2name operation, the first matching value is returned.
- */
-typedef struct {
-       const char *name;
-       int         value;
-} Jim_Nvp;
-
-
-int Jim_GetNvp (Jim_Interp *interp,
-                                                                       Jim_Obj *objPtr,
-                                                                       const Jim_Nvp *nvp_table,
-                                                                       const Jim_Nvp **result);
-
-/* Name Value Pairs Operations */
-Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp *nvp_table, const char *name);
-Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp *nvp_table, const char *name);
-Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp *nvp_table, int v);
-
-int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result);
-int Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result);
-int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp *nvp_table, int value, Jim_Nvp **result);
-
-int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result);
-int Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result);
-int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *value_obj, Jim_Nvp **result);
-
-/** prints a nice 'unknown' parameter error message to the 'result' */
-void Jim_SetResult_NvpUnknown(Jim_Interp *interp,
-                                                                                                  Jim_Obj *param_name,
-                                                                                                  Jim_Obj *param_value,
-                                                                                                  const Jim_Nvp *nvp_table);
-
-
-/** Debug: convert argc/argv into a printable string for printf() debug
- *
- * \param interp - the interpeter
- * \param argc   - arg count
- * \param argv   - the objects
- *
- * \returns string pointer holding the text.
- *
- * Note, next call to this function will free the old (last) string.
- *
- * For example might want do this:
- * \code
- *     fp = fopen("some.file.log", "a");
- *     fprintf(fp, "PARAMS are: %s\n", Jim_DebugArgvString(interp, argc, argv));
- *     fclose(fp);
- * \endcode
- */
-const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-
-
-/** A TCL -ish GetOpt like code.
- *
- * Some TCL objects have various "configuration" values.
- * For example - in Tcl/Tk the "buttons" have many options.
- *
- * Usefull when dealing with command options.
- * that may come in any order...
- *
- * Does not support "-foo = 123" type options.
- * Only supports tcl type options, like "-foo 123"
- */
-
-typedef struct jim_getopt {
-       Jim_Interp     *interp;
-       int            argc;
-       Jim_Obj        * const * argv;
-       int            isconfigure; /* non-zero if configure */
-} Jim_GetOptInfo;
-
-/** GetOpt - how to.
- *
- * Example (short and incomplete):
- * \code
- *   Jim_GetOptInfo goi;
- *
- *   Jim_GetOpt_Setup(&goi, interp, argc, argv);
- *
- *   while (goi.argc) {
- *         e = Jim_GetOpt_Nvp(&goi, nvp_options, &n);
- *         if (e != JIM_OK) {
- *               Jim_GetOpt_NvpUnknown(&goi, nvp_options, 0);
- *               return e;
- *         }
- *
- *         switch (n->value) {
- *         case ALIVE:
- *             printf("Option ALIVE specified\n");
- *             break;
- *         case FIRST:
- *             if (goi.argc < 1) {
- *                     .. not enough args error ..
- *             }
- *             Jim_GetOpt_String(&goi, &cp, NULL);
- *             printf("FIRSTNAME: %s\n", cp);
- *         case AGE:
- *             Jim_GetOpt_Wide(&goi, &w);
- *             printf("AGE: %d\n", (int)(w));
- *             break;
- *         case POLITICS:
- *             e = Jim_GetOpt_Nvp(&goi, nvp_politics, &n);
- *             if (e != JIM_OK) {
- *                 Jim_GetOpt_NvpUnknown(&goi, nvp_politics, 1);
- *                 return e;
- *             }
- *         }
- *  }
- *
- * \endcode
- *
- */
-
-/** Setup GETOPT
- *
- * \param goi    - get opt info to be initialized
- * \param interp - jim interp
- * \param argc   - argc count.
- * \param argv   - argv (will be copied)
- *
- * \code
- *     Jim_GetOptInfo  goi;
- *
- *     Jim_GetOptSetup(&goi, interp, argc, argv);
- * \endcode
- */
-
-int Jim_GetOpt_Setup(Jim_GetOptInfo *goi,
-                                                                                       Jim_Interp *interp,
-                                                                                       int argc,
-                                                                                       Jim_Obj * const *  argv);
-
-
-/** Debug - Dump parameters to stderr
- * \param goi - current parameters
- */
-void Jim_GetOpt_Debug(Jim_GetOptInfo *goi);
-
-
-
-/** Remove argv[0] from the list.
- *
- * \param goi - get opt info
- * \param puthere - where param is put
- *
- */
-int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere);
-
-/** Remove argv[0] as string.
- *
- * \param goi     - get opt info
- * \param puthere - where param is put
- * \param len     - return its length
- */
-int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len);
-
-/** Remove argv[0] as double.
- *
- * \param goi     - get opt info
- * \param puthere - where param is put.
- *
- */
-int Jim_GetOpt_Double(Jim_GetOptInfo *goi, double *puthere);
-
-/** Remove argv[0] as wide.
- *
- * \param goi     - get opt info
- * \param puthere - where param is put.
- */
-int Jim_GetOpt_Wide(Jim_GetOptInfo *goi, jim_wide *puthere);
-
-/** Remove argv[0] as NVP.
- *
- * \param goi     - get opt info
- * \param lookup  - nvp lookup table
- * \param puthere - where param is put.
- *
- */
-int Jim_GetOpt_Nvp(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, Jim_Nvp **puthere);
-
-/** Create an appropriate error message for an NVP.
- *
- * \param goi - options info
- * \param lookup - the NVP table that was used.
- * \param hadprefix - 0 or 1 if the option had a prefix.
- *
- * This function will set the "interp->result" to a human readable
- * error message listing the available options.
- *
- * This function assumes the previous option argv[-1] is the unknown string.
- *
- * If this option had some prefix, then pass "hadprefix = 1" else pass "hadprefix = 0"
- *
- * Example:
- * \code
- *
- *  while (goi.argc) {
- *     // Get the next option
- *     e = Jim_GetOpt_Nvp(&goi, cmd_options, &n);
- *     if (e != JIM_OK) {
- *          // option was not recognized
- *          // pass 'hadprefix = 0' because there is no prefix
- *          Jim_GetOpt_NvpUnknown(&goi, cmd_options, 0);
- *          return e;
- *     }
- *
- *     switch (n->value) {
- *     case OPT_SEX:
- *          // handle:  --sex male | female | lots | needmore
- *          e = Jim_GetOpt_Nvp(&goi, &nvp_sex, &n);
- *          if (e != JIM_OK) {
- *               Jim_GetOpt_NvpUnknown(&ogi, nvp_sex, 1);
- *               return e;
- *          }
- *          printf("Code: (%d) is %s\n", n->value, n->name);
- *          break;
- *     case ...:
- *          [snip]
- *     }
- * }
- * \endcode
- *
- */
-void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, int hadprefix);
-
-
-/** Remove argv[0] as Enum
- *
- * \param goi     - get opt info
- * \param lookup  - lookup table.
- * \param puthere - where param is put.
- *
- */
-int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char * const *  lookup, int *puthere);
-
-#endif
index 88bf2c1..0fdd445 100644 (file)
@@ -191,9 +191,83 @@ static void JimSetBitsIntLittleEndian(unsigned char *bitvec, jim_wide value, int
 }
 
 /**
+ * Binary conversion of jim_wide integer to float
+ *
+ * Considers the least significant bits of
+ * jim_wide 'value' as a IEEE float.
+ *
+ * Should work for both little- and big-endian platforms.
+ */
+static float JimIntToFloat(jim_wide value)
+{
+    int offs;
+    float val;
+
+    /* Skip offs to get to least significant bytes */
+    offs = Jim_IsBigEndian() ? (sizeof(jim_wide) - sizeof(float)) : 0;
+
+    memcpy(&val, (unsigned char *) &value + offs, sizeof(float));
+    return val;
+}
+
+/**
+ * Binary conversion of jim_wide integer to double
+ *
+ * Double precision version of JimIntToFloat
+ */
+static double JimIntToDouble(jim_wide value)
+{
+    int offs;
+    double val;
+
+    /* Skip offs to get to least significant bytes */
+    offs = Jim_IsBigEndian() ? (sizeof(jim_wide) - sizeof(double)) : 0;
+
+    memcpy(&val, (unsigned char *) &value + offs, sizeof(double));
+    return val;
+}
+
+/**
+ * Binary conversion of float to jim_wide integer
+ *
+ * Considers the bits of IEEE float 'value' as integer.
+ * The integer is zero-extended to jim_wide.
+ *
+ * Should work for both little- and big-endian platforms.
+ */
+static jim_wide JimFloatToInt(float value)
+{
+    int offs;
+    jim_wide val = 0;
+
+    /* Skip offs to get to least significant bytes */
+    offs = Jim_IsBigEndian() ? (sizeof(jim_wide) - sizeof(float)) : 0;
+
+    memcpy((unsigned char *) &val + offs, &value, sizeof(float));
+    return val;
+}
+
+/**
+ * Binary conversion of double to jim_wide integer
+ *
+ * Double precision version of JimFloatToInt
+ */
+static jim_wide JimDoubleToInt(double value)
+{
+    int offs;
+    jim_wide val = 0;
+
+    /* Skip offs to get to least significant bytes */
+    offs = Jim_IsBigEndian() ? (sizeof(jim_wide) - sizeof(double)) : 0;
+
+    memcpy((unsigned char *) &val + offs, &value, sizeof(double));
+    return val;
+}
+
+/**
  * [unpack]
  *
- * Usage: unpack binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth
+ * Usage: unpack binvalue -intbe|-intle|-uintbe|-uintle|-floatbe|-floatle|-str bitpos bitwidth
  *
  * Unpacks bits from $binvalue at bit position $bitpos and with $bitwidth.
  * Interprets the value according to the type and returns it.
@@ -201,13 +275,15 @@ static void JimSetBitsIntLittleEndian(unsigned char *bitvec, jim_wide value, int
 static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     int option;
-    static const char * const options[] = { "-intbe", "-intle", "-uintbe", "-uintle", "-str", NULL };
-    enum { OPT_INTBE, OPT_INTLE, OPT_UINTBE, OPT_UINTLE, OPT_STR, };
+    static const char * const options[] = { "-intbe", "-intle", "-uintbe", "-uintle",
+        "-floatbe", "-floatle", "-str", NULL };
+    enum { OPT_INTBE, OPT_INTLE, OPT_UINTBE, OPT_UINTLE, OPT_FLOATBE, OPT_FLOATLE, OPT_STR, };
     jim_wide pos;
     jim_wide width;
 
     if (argc != 5) {
-        Jim_WrongNumArgs(interp, 1, argv, "binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth");
+        Jim_WrongNumArgs(interp, 1, argv,
+                "binvalue -intbe|-intle|-uintbe|-uintle|-floatbe|-floatle|-str bitpos bitwidth");
         return JIM_ERR;
     }
     if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
@@ -252,7 +328,7 @@ static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
             if (pos + width > len * 8) {
                 width = len * 8 - pos;
             }
-            if (option == OPT_INTBE || option == OPT_UINTBE) {
+            if (option == OPT_INTBE || option == OPT_UINTBE || option == OPT_FLOATBE) {
                 result = JimBitIntBigEndian(str, pos, width);
             }
             else {
@@ -261,8 +337,23 @@ static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
             if (option == OPT_INTBE || option == OPT_INTLE) {
                 result = JimSignExtend(result, width);
             }
+
+        }
+
+        if (option == OPT_FLOATBE || option == OPT_FLOATLE) {
+            double fresult;
+            if (width == 32) {
+                fresult = (double) JimIntToFloat(result);
+            } else if (width == 64) {
+                fresult = JimIntToDouble(result);
+            } else {
+                Jim_SetResultFormatted(interp, "float field has bad bitwidth: %#s", argv[4]);
+                return JIM_ERR;
+            }
+            Jim_SetResult(interp, Jim_NewDoubleObj(interp, fresult));
+        } else {
+            Jim_SetResultInt(interp, result);
         }
-        Jim_SetResultInt(interp, result);
         return JIM_OK;
     }
 }
@@ -270,7 +361,7 @@ static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 /**
  * [pack]
  *
- * Usage: pack varname value -intle|-intbe|-str width ?bitoffset?
+ * Usage: pack varname value -intbe|-intle|-floatle|-floatbe|-str width ?bitoffset?
  *
  * Packs the binary representation of 'value' into the variable of the given name.
  * The value is packed according to the given type, width and bitoffset.
@@ -280,30 +371,39 @@ static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 static int Jim_PackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     int option;
-    static const char * const options[] = { "-intle", "-intbe", "-str", NULL };
-    enum { OPT_LE, OPT_BE, OPT_STR };
+    static const char * const options[] = { "-intle", "-intbe", "-floatle", "-floatbe",
+        "-str", NULL };
+    enum { OPT_LE, OPT_BE, OPT_FLOATLE, OPT_FLOATBE, OPT_STR };
     jim_wide pos = 0;
     jim_wide width;
     jim_wide value;
+    double fvalue;
     Jim_Obj *stringObjPtr;
     int len;
     int freeobj = 0;
 
     if (argc != 5 && argc != 6) {
-        Jim_WrongNumArgs(interp, 1, argv, "varName value -intle|-intbe|-str bitwidth ?bitoffset?");
+        Jim_WrongNumArgs(interp, 1, argv,
+                "varName value -intle|-intbe|-floatle|-floatbe|-str bitwidth ?bitoffset?");
         return JIM_ERR;
     }
     if (Jim_GetEnum(interp, argv[3], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
         return JIM_ERR;
     }
-    if (option != OPT_STR && Jim_GetWide(interp, argv[2], &value) != JIM_OK) {
+    if ((option == OPT_LE || option == OPT_BE) &&
+            Jim_GetWide(interp, argv[2], &value) != JIM_OK) {
+        return JIM_ERR;
+    }
+    if ((option == OPT_FLOATLE || option == OPT_FLOATBE) &&
+            Jim_GetDouble(interp, argv[2], &fvalue) != JIM_OK) {
         return JIM_ERR;
     }
     if (Jim_GetWide(interp, argv[4], &width) != JIM_OK) {
         return JIM_ERR;
     }
-    if (width <= 0 || (option == OPT_STR && width % 8) || (option != OPT_STR && width > sizeof(jim_wide) * 8)) {
-        Jim_SetResultFormatted(interp, "bad bitwidth: %#s", argv[5]);
+    if (width <= 0 || (option == OPT_STR && width % 8) || (option != OPT_STR && width > sizeof(jim_wide) * 8) ||
+       ((option == OPT_FLOATLE || option == OPT_FLOATBE) && width != 32 && width != 64)) {
+        Jim_SetResultFormatted(interp, "bad bitwidth: %#s", argv[4]);
         return JIM_ERR;
     }
     if (argc == 6) {
@@ -342,10 +442,19 @@ static int Jim_PackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
      */
     Jim_AppendString(interp, stringObjPtr, "", 0);
 
-    if (option == OPT_BE) {
+    /* Convert floating point to integer if necessary */
+    if (option == OPT_FLOATLE || option == OPT_FLOATBE) {
+        /* Note that the following is slightly incompatible with Tcl behaviour.
+         * In Tcl floating overflow gives FLT_MAX (cf. test binary-13.13).
+         * In Jim Tcl it gives Infinity. This behavior may change.
+         */
+        value = (width == 32) ? JimFloatToInt((float)fvalue) : JimDoubleToInt(fvalue);
+    }
+
+    if (option == OPT_BE || option == OPT_FLOATBE) {
         JimSetBitsIntBigEndian((unsigned char *)stringObjPtr->bytes, value, pos, width);
     }
-    else if (option == OPT_LE) {
+    else if (option == OPT_LE || option == OPT_FLOATLE) {
         JimSetBitsIntLittleEndian((unsigned char *)stringObjPtr->bytes, value, pos, width);
     }
     else {
@@ -355,7 +464,7 @@ static int Jim_PackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         if (width > Jim_Length(argv[2])) {
             width = Jim_Length(argv[2]);
         }
-        memcpy(stringObjPtr->bytes + pos, Jim_GetString(argv[2], NULL), width);
+        memcpy(stringObjPtr->bytes + pos, Jim_String(argv[2]), width);
         /* No padding is needed since the string is already extended */
     }
 
index 9caec0d..8b37c0a 100644 (file)
@@ -1,9 +1,16 @@
-#include <unistd.h>
 #include <string.h>
 
-#include "jim.h"
 #include "jimautoconf.h"
-#include "jim-subcmd.h"
+#include <jim-subcmd.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#else
+#define R_OK 4
+#endif
+
+/* All packages have a fixed, dummy version */
+static const char *package_version_1 = "1.0";
 
 /* -----------------------------------------------------------------------------
  * Packages handling
@@ -21,34 +28,38 @@ int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, in
         }
         return JIM_ERR;
     }
-    if (he) {
-        Jim_DeleteHashEntry(&interp->packages, name);
-    }
-    Jim_AddHashEntry(&interp->packages, name, (char *)ver);
+    Jim_ReplaceHashEntry(&interp->packages, name, (char *)ver);
     return JIM_OK;
 }
 
-static char *JimFindPackage(Jim_Interp *interp, char **prefixes, int prefixc, const char *pkgName)
+/**
+ * Searches along a of paths for the given package.
+ *
+ * Returns the allocated path to the package file if found,
+ * or NULL if not found.
+ */
+static char *JimFindPackage(Jim_Interp *interp, Jim_Obj *prefixListObj, const char *pkgName)
 {
     int i;
     char *buf = Jim_Alloc(JIM_PATH_LEN);
+    int prefixc = Jim_ListLength(interp, prefixListObj);
 
     for (i = 0; i < prefixc; i++) {
-        if (prefixes[i] == NULL)
-            continue;
+        Jim_Obj *prefixObjPtr = Jim_ListGetIndex(interp, prefixListObj, i);
+        const char *prefix = Jim_String(prefixObjPtr);
 
         /* Loadable modules are tried first */
 #ifdef jim_ext_load
-        snprintf(buf, JIM_PATH_LEN, "%s/%s.so", prefixes[i], pkgName);
+        snprintf(buf, JIM_PATH_LEN, "%s/%s.so", prefix, pkgName);
         if (access(buf, R_OK) == 0) {
             return buf;
         }
 #endif
-        if (strcmp(prefixes[i], ".") == 0) {
+        if (strcmp(prefix, ".") == 0) {
             snprintf(buf, JIM_PATH_LEN, "%s.tcl", pkgName);
         }
         else {
-            snprintf(buf, JIM_PATH_LEN, "%s/%s.tcl", prefixes[i], pkgName);
+            snprintf(buf, JIM_PATH_LEN, "%s/%s.tcl", prefix, pkgName);
         }
 
         if (access(buf, R_OK) == 0) {
@@ -64,63 +75,45 @@ static char *JimFindPackage(Jim_Interp *interp, char **prefixes, int prefixc, co
  * JIM_OK is returned, otherwise JIM_ERR is returned. */
 static int JimLoadPackage(Jim_Interp *interp, const char *name, int flags)
 {
-    Jim_Obj *libPathObjPtr;
-    char **prefixes, *path;
-    int prefixc, i, retCode = JIM_ERR;
-
-    libPathObjPtr = Jim_GetGlobalVariableStr(interp, JIM_LIBPATH, JIM_NONE);
-    if (libPathObjPtr == NULL) {
-        prefixc = 0;
-        libPathObjPtr = NULL;
-    }
-    else {
-        Jim_IncrRefCount(libPathObjPtr);
-        prefixc = Jim_ListLength(interp, libPathObjPtr);
-    }
-
-    prefixes = Jim_Alloc(sizeof(char *) * prefixc);
-    for (i = 0; i < prefixc; i++) {
-        Jim_Obj *prefixObjPtr;
-
-        if (Jim_ListIndex(interp, libPathObjPtr, i, &prefixObjPtr, JIM_NONE) != JIM_OK) {
-            prefixes[i] = NULL;
-            continue;
-        }
-        prefixes[i] = Jim_StrDup(Jim_String(prefixObjPtr));
-    }
-
-    /* Scan every directory for the the first match */
-    path = JimFindPackage(interp, prefixes, prefixc, name);
-    if (path != NULL) {
-        char *p = strrchr(path, '.');
-
-        /* Note: Even if the file fails to load, we consider the package loaded.
-         *       This prevents issues with recursion.
-         *       Use a dummy version of "" to signify this case.
-         */
-        Jim_PackageProvide(interp, name, "", 0);
-
-        /* Try to load/source it */
-        if (p && strcmp(p, ".tcl") == 0) {
-            retCode = Jim_EvalFileGlobal(interp, path);
-        }
+    int retCode = JIM_ERR;
+    Jim_Obj *libPathObjPtr = Jim_GetGlobalVariableStr(interp, JIM_LIBPATH, JIM_NONE);
+    if (libPathObjPtr) {
+        char *path;
+
+        /* Scan every directory for the the first match */
+        path = JimFindPackage(interp, libPathObjPtr, name);
+        if (path) {
+            const char *p;
+
+            /* Note: Even if the file fails to load, we consider the package loaded.
+             *       This prevents issues with recursion.
+             *       Use a dummy version of "" to signify this case.
+             */
+            Jim_PackageProvide(interp, name, "", 0);
+
+            /* Try to load/source it */
+            p = strrchr(path, '.');
+
+            if (p && strcmp(p, ".tcl") == 0) {
+                Jim_IncrRefCount(libPathObjPtr);
+                retCode = Jim_EvalFileGlobal(interp, path);
+                Jim_DecrRefCount(interp, libPathObjPtr);
+            }
 #ifdef jim_ext_load
-        else {
-            retCode = Jim_LoadLibrary(interp, path);
-        }
+            else {
+                retCode = Jim_LoadLibrary(interp, path);
+            }
 #endif
-        if (retCode != JIM_OK) {
-            /* Upon failure, remove the dummy entry */
-            Jim_DeleteHashEntry(&interp->packages, name);
+            if (retCode != JIM_OK) {
+                /* Upon failure, remove the dummy entry */
+                Jim_DeleteHashEntry(&interp->packages, name);
+            }
+            Jim_Free(path);
         }
-        Jim_Free(path);
+
+        return retCode;
     }
-    for (i = 0; i < prefixc; i++)
-        Jim_Free(prefixes[i]);
-    Jim_Free(prefixes);
-    if (libPathObjPtr)
-        Jim_DecrRefCount(interp, libPathObjPtr);
-    return retCode;
+    return JIM_ERR;
 }
 
 int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags)
@@ -128,7 +121,7 @@ int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags)
     Jim_HashEntry *he;
 
     /* Start with an empty error string */
-    Jim_SetResultString(interp, "", 0);
+    Jim_SetEmptyResult(interp);
 
     he = Jim_FindHashEntry(&interp->packages, name);
     if (he == NULL) {
@@ -136,17 +129,15 @@ int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags)
         int retcode = JimLoadPackage(interp, name, flags);
         if (retcode != JIM_OK) {
             if (flags & JIM_ERRMSG) {
-                int len;
-
-                Jim_GetString(Jim_GetResult(interp), &len);
+                int len = Jim_Length(Jim_GetResult(interp));
                 Jim_SetResultFormatted(interp, "%#s%sCan't load package %s",
                     Jim_GetResult(interp), len ? "\n" : "", name);
             }
             return retcode;
         }
 
-        /* In case the package did no 'package provide' */
-        Jim_PackageProvide(interp, name, "1.0", 0);
+        /* In case the package did not 'package provide' */
+        Jim_PackageProvide(interp, name, package_version_1, 0);
 
         /* Now it must exist */
         he = Jim_FindHashEntry(&interp->packages, name);
@@ -161,24 +152,18 @@ int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags)
  *
  * package provide name ?version?
  *
- *      This procedure is invoked to declare that a particular version
- *      of a particular package is now present in an interpreter.  There
- *      must not be any other version of this package already
- *      provided in the interpreter.
+ *      This procedure is invoked to declare that
+ *      a particular package is now present in an interpreter.
+ *      The package must not already be provided in the interpreter.
  *
  * Results:
- *      Returns JIM_OK and sets the package version (or 1.0 if not specified).
+ *      Returns JIM_OK and sets results as "1.0" (the given version is ignored)
  *
  *----------------------------------------------------------------------
  */
 static int package_cmd_provide(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    const char *version = "1.0";
-
-    if (argc == 2) {
-        version = Jim_String(argv[1]);
-    }
-    return Jim_PackageProvide(interp, Jim_String(argv[0]), version, JIM_ERRMSG);
+    return Jim_PackageProvide(interp, Jim_String(argv[0]), package_version_1, JIM_ERRMSG);
 }
 
 /*
@@ -232,24 +217,33 @@ static int package_cmd_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 }
 
 static const jim_subcmd_type package_command_table[] = {
-    {.cmd = "provide",
-            .args = "name ?version?",
-            .function = package_cmd_provide,
-            .minargs = 1,
-            .maxargs = 2,
-        .description = "Indicates that the current script provides the given package"},
-    {.cmd = "require",
-            .args = "name ?version?",
-            .function = package_cmd_require,
-            .minargs = 1,
-            .maxargs = 2,
-        .description = "Loads the given package by looking in standard places"},
-    {.cmd = "list",
-            .function = package_cmd_list,
-            .minargs = 0,
-            .maxargs = 0,
-        .description = "Lists all known packages"},
-    {0}
+    {
+        "provide",
+        "name ?version?",
+        package_cmd_provide,
+        1,
+        2,
+        /* Description: Indicates that the current script provides the given package */
+    },
+    {
+        "require",
+        "name ?version?",
+        package_cmd_require,
+        1,
+        2,
+        /* Description: Loads the given package by looking in standard places */
+    },
+    {
+        "list",
+        NULL,
+        package_cmd_list,
+        0,
+        0,
+        /* Description: Lists all known packages */
+    },
+    {
+        NULL
+    }
 };
 
 int Jim_packageInit(Jim_Interp *interp)
index 0cf3604..af8c0f1 100644 (file)
@@ -1,21 +1,35 @@
-
-/* Jim - POSIX extension
- * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
+/*
+ * Jim - POSIX extension
  *
- * A copy of the license is also included in the source distribution
- * of Jim, as a TXT file name called LICENSE.
+ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
  */
 
 #include <sys/types.h>
@@ -26,8 +40,8 @@
 #include <signal.h>
 #include <errno.h>
 
-#include "jim.h"
 #include "jimautoconf.h"
+#include <jim.h>
 
 #ifdef HAVE_SYS_SYSINFO_H
 #include <sys/sysinfo.h>
@@ -173,6 +187,7 @@ static int Jim_PosixGethostnameCommand(Jim_Interp *interp, int argc, Jim_Obj *co
     buf = Jim_Alloc(JIM_HOST_NAME_MAX);
     if (gethostname(buf, JIM_HOST_NAME_MAX) == -1) {
         Jim_PosixSetError(interp);
+        Jim_Free(buf);
         rc = JIM_ERR;
     }
     else {
index 67fc956..d7c0e40 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Tcl readdir command.
  *
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
-#include <dirent.h>
 
-#include "jim.h"
-#include "jimautoconf.h"
+#include <jim.h>
+#include <jimautoconf.h>
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
 
 /*
  *-----------------------------------------------------------------------------
@@ -89,24 +91,25 @@ int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         Jim_SetResultString(interp, strerror(errno), -1);
         return JIM_ERR;
     }
-    Jim_SetResultString(interp, strerror(errno), -1);
-
-    Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+    else {
+        Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
 
-    while ((entryPtr = readdir(dirPtr)) != NULL) {
-        if (entryPtr->d_name[0] == '.') {
-            if (entryPtr->d_name[1] == '\0') {
-                continue;
+        while ((entryPtr = readdir(dirPtr)) != NULL) {
+            if (entryPtr->d_name[0] == '.') {
+                if (entryPtr->d_name[1] == '\0') {
+                    continue;
+                }
+                if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
+                    continue;
             }
-            if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0'))
-                continue;
+            Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1));
         }
-        Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp,
-                entryPtr->d_name, -1));
-    }
-    closedir(dirPtr);
+        closedir(dirPtr);
 
-    return JIM_OK;
+        Jim_SetResult(interp, listObj);
+
+        return JIM_OK;
+    }
 }
 
 int Jim_readdirInit(Jim_Interp *interp)
index 3990d0c..39051b0 100644 (file)
@@ -1,25 +1,38 @@
-
-/* Jim - Readline bindings for Jim
+/*
+ * Jim - Readline bindings for Jim
+ *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
  *
- * A copy of the license is also included in the source distribution
- * of Jim, as a TXT file name called LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
  */
 
-#include "jim.h"
-#include "jimautoconf.h"
+#include <jim.h>
 
 #include <readline/readline.h>
 #include <readline/history.h>
index 2ccd996..25ffd21 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include "jim.h"
 #include "jimautoconf.h"
-#include "jimregexp.h"
+#if defined(JIM_REGEXP)
+    #include "jimregexp.h"
+#else
+    #include <regex.h>
+#endif
+#include "jim.h"
 
 static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
 {
index 2e700eb..27e49c4 100644 (file)
@@ -1,21 +1,35 @@
-
-/* Jim - SDL extension
+/*
+ * Jim - SDL extension
+ *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
  *
- * A copy of the license is also included in the source distribution
- * of Jim, as a TXT file name called LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
  */
 
 #include <stdio.h>
@@ -25,8 +39,7 @@
 #include <SDL/SDL.h>
 #include <SDL/SDL_gfxPrimitives.h>
 
-#include "jim.h"
-#include "jimautoconf.h"
+#include <jim.h>
 
 #define AIO_CMD_LEN 128
 
@@ -215,7 +228,7 @@ static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
     jss->screen = screen;
     sprintf(buf, "sdl.surface%ld", screenId);
     Jim_CreateCommand(interp, buf, JimSdlHandlerCommand, jss, JimSdlDelProc);
-    Jim_SetResultString(interp, buf, -1);
+    Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
     return JIM_OK;
 }
 
index 6a2a2be..a819a92 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * jim-signal.c
  *
@@ -9,17 +8,19 @@
 #include <ctype.h>
 #include <unistd.h>
 
-#include "jim.h"
 #include "jimautoconf.h"
-#include "jim-subcmd.h"
-#include "jim-signal.h"
+#include <jim-subcmd.h>
+#include <jim-signal.h>
 
 #define MAX_SIGNALS (sizeof(jim_wide) * 8)
 
 static jim_wide *sigloc;
 static jim_wide sigsblocked;
 static struct sigaction *sa_old;
-static int signal_handling[MAX_SIGNALS];
+static struct {
+    int status;
+    const char *name;
+} siginfo[MAX_SIGNALS];
 
 /* Make sure to do this as a wide, not int */
 #define sig_to_bit(SIG) ((jim_wide)1 << (SIG))
@@ -38,6 +39,61 @@ static void signal_ignorer(int sig)
     sigsblocked |= sig_to_bit(sig);
 }
 
+static void signal_init_names(void)
+{
+#define SET_SIG_NAME(SIG) siginfo[SIG].name = #SIG
+
+    SET_SIG_NAME(SIGABRT);
+    SET_SIG_NAME(SIGALRM);
+    SET_SIG_NAME(SIGBUS);
+    SET_SIG_NAME(SIGCHLD);
+    SET_SIG_NAME(SIGCONT);
+    SET_SIG_NAME(SIGFPE);
+    SET_SIG_NAME(SIGHUP);
+    SET_SIG_NAME(SIGILL);
+    SET_SIG_NAME(SIGINT);
+#ifdef SIGIO
+    SET_SIG_NAME(SIGIO);
+#endif
+    SET_SIG_NAME(SIGKILL);
+    SET_SIG_NAME(SIGPIPE);
+    SET_SIG_NAME(SIGPROF);
+    SET_SIG_NAME(SIGQUIT);
+    SET_SIG_NAME(SIGSEGV);
+    SET_SIG_NAME(SIGSTOP);
+    SET_SIG_NAME(SIGSYS);
+    SET_SIG_NAME(SIGTERM);
+    SET_SIG_NAME(SIGTRAP);
+    SET_SIG_NAME(SIGTSTP);
+    SET_SIG_NAME(SIGTTIN);
+    SET_SIG_NAME(SIGTTOU);
+    SET_SIG_NAME(SIGURG);
+    SET_SIG_NAME(SIGUSR1);
+    SET_SIG_NAME(SIGUSR2);
+    SET_SIG_NAME(SIGVTALRM);
+    SET_SIG_NAME(SIGWINCH);
+    SET_SIG_NAME(SIGXCPU);
+    SET_SIG_NAME(SIGXFSZ);
+#ifdef SIGPWR
+    SET_SIG_NAME(SIGPWR);
+#endif
+#ifdef SIGCLD
+    SET_SIG_NAME(SIGCLD);
+#endif
+#ifdef SIGEMT
+    SET_SIG_NAME(SIGEMT);
+#endif
+#ifdef SIGLOST
+    SET_SIG_NAME(SIGLOST);
+#endif
+#ifdef SIGPOLL
+    SET_SIG_NAME(SIGPOLL);
+#endif
+#ifdef SIGINFO
+    SET_SIG_NAME(SIGINFO);
+#endif
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -55,59 +111,13 @@ static void signal_ignorer(int sig)
  *
  *----------------------------------------------------------------------
  */
-#define CHECK_SIG(NAME) if (sig == NAME) return #NAME
-
 const char *Jim_SignalId(int sig)
 {
-    CHECK_SIG(SIGABRT);
-    CHECK_SIG(SIGALRM);
-    CHECK_SIG(SIGBUS);
-    CHECK_SIG(SIGCHLD);
-    CHECK_SIG(SIGCONT);
-    CHECK_SIG(SIGFPE);
-    CHECK_SIG(SIGHUP);
-    CHECK_SIG(SIGILL);
-    CHECK_SIG(SIGINT);
-#ifdef SIGIO
-    CHECK_SIG(SIGIO);
-#endif
-    CHECK_SIG(SIGKILL);
-    CHECK_SIG(SIGPIPE);
-    CHECK_SIG(SIGPROF);
-    CHECK_SIG(SIGQUIT);
-    CHECK_SIG(SIGSEGV);
-    CHECK_SIG(SIGSTOP);
-    CHECK_SIG(SIGSYS);
-    CHECK_SIG(SIGTERM);
-    CHECK_SIG(SIGTRAP);
-    CHECK_SIG(SIGTSTP);
-    CHECK_SIG(SIGTTIN);
-    CHECK_SIG(SIGTTOU);
-    CHECK_SIG(SIGURG);
-    CHECK_SIG(SIGUSR1);
-    CHECK_SIG(SIGUSR2);
-    CHECK_SIG(SIGVTALRM);
-    CHECK_SIG(SIGWINCH);
-    CHECK_SIG(SIGXCPU);
-    CHECK_SIG(SIGXFSZ);
-#ifdef SIGPWR
-    CHECK_SIG(SIGPWR);
-#endif
-#ifdef SIGCLD
-    CHECK_SIG(SIGCLD);
-#endif
-#ifdef SIGEMT
-    CHECK_SIG(SIGEMT);
-#endif
-#ifdef SIGLOST
-    CHECK_SIG(SIGLOST);
-#endif
-#ifdef SIGPOLL
-    CHECK_SIG(SIGPOLL);
-#endif
-#ifdef SIGINFO
-    CHECK_SIG(SIGINFO);
-#endif
+    if (sig >=0 && sig < MAX_SIGNALS) {
+        if (siginfo[sig].name) {
+            return siginfo[sig].name;
+        }
+    }
     return "unknown signal";
 }
 
@@ -148,15 +158,14 @@ static int find_signal_by_name(Jim_Interp *interp, const char *name)
     else {
         for (i = 1; i < MAX_SIGNALS; i++) {
             /* Jim_SignalId() returns names such as SIGINT, and
-             * returns "unknown signal id" if unknown, so this will work
+             * returns "unknown signal" if unknown, so this will work
              */
             if (strcasecmp(Jim_SignalId(i) + 3, pt) == 0) {
                 return i;
             }
         }
     }
-    Jim_SetResultString(interp, "unknown signal ", -1);
-    Jim_AppendString(interp, Jim_GetResult(interp), name, -1);
+    Jim_SetResultFormatted(interp, "unknown signal %s", name);
 
     return -1;
 }
@@ -173,7 +182,7 @@ static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *cons
     if (argc == 0) {
         Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
         for (i = 1; i < MAX_SIGNALS; i++) {
-            if (signal_handling[i] == action) {
+            if (siginfo[i].status == action) {
                 /* Add signal name to the list  */
                 Jim_ListAppendElement(interp, Jim_GetResult(interp),
                     Jim_NewStringObj(interp, Jim_SignalId(i), -1));
@@ -184,8 +193,7 @@ static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *cons
 
     /* Catch all the signals we care about */
     if (action != SIGNAL_ACTION_DEFAULT) {
-        sa.sa_flags = 0;
-        sigemptyset(&sa.sa_mask);
+        memset(&sa, 0, sizeof(sa));
         if (action == SIGNAL_ACTION_HANDLE) {
             sa.sa_handler = signal_handler;
         }
@@ -201,12 +209,12 @@ static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *cons
         if (sig < 0) {
             return JIM_ERR;
         }
-        if (action != signal_handling[sig]) {
+        if (action != siginfo[sig].status) {
             /* Need to change the action for this signal */
             switch (action) {
                 case SIGNAL_ACTION_HANDLE:
                 case SIGNAL_ACTION_IGNORE:
-                    if (signal_handling[sig] == SIGNAL_ACTION_DEFAULT) {
+                    if (siginfo[sig].status == SIGNAL_ACTION_DEFAULT) {
                         if (!sa_old) {
                             /* Allocate the structure the first time through */
                             sa_old = Jim_Alloc(sizeof(*sa_old) * MAX_SIGNALS);
@@ -224,7 +232,7 @@ static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *cons
                         sigaction(sig, &sa_old[sig], 0);
                     }
             }
-            signal_handling[sig] = action;
+            siginfo[sig].status = action;
         }
     }
 
@@ -312,7 +320,7 @@ static int signal_cmd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     }
 
     /* If the signal is ignored (blocked) ... */
-    if (signal_handling[sig] == SIGNAL_ACTION_IGNORE) {
+    if (siginfo[sig].status == SIGNAL_ACTION_IGNORE) {
         sigsblocked |= sig_to_bit(sig);
         return JIM_OK;
     }
@@ -351,42 +359,42 @@ static int signal_cmd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
  *-----------------------------------------------------------------------------
  */
 static const jim_subcmd_type signal_command_table[] = {
-    {   .cmd = "handle",
-        .args = "?signals ...?",
-        .function = signal_cmd_handle,
-        .minargs = 0,
-        .maxargs = -1,
-        .description = "Lists handled signals, or adds to handled signals"
+    {   "handle",
+        "?signals ...?",
+        signal_cmd_handle,
+        0,
+        -1,
+        /* Description: Lists handled signals, or adds to handled signals */
     },
-    {   .cmd = "ignore",
-        .args = "?signals ...?",
-        .function = signal_cmd_ignore,
-        .minargs = 0,
-        .maxargs = -1,
-        .description = "Lists ignored signals, or adds to ignored signals"
+    {   "ignore",
+        "?signals ...?",
+        signal_cmd_ignore,
+        0,
+        -1,
+        /* Description: Lists ignored signals, or adds to ignored signals */
     },
-    {   .cmd = "default",
-        .args = "?signals ...?",
-        .function = signal_cmd_default,
-        .minargs = 0,
-        .maxargs = -1,
-        .description = "Lists defaulted signals, or adds to defaulted signals"
+    {   "default",
+        "?signals ...?",
+        signal_cmd_default,
+        0,
+        -1,
+        /* Description: Lists defaulted signals, or adds to defaulted signals */
     },
-    {   .cmd = "check",
-        .args = "?-clear? ?signals ...?",
-        .function = signal_cmd_check,
-        .minargs = 0,
-        .maxargs = -1,
-        .description = "Returns ignored signals which have occurred, and optionally clearing them"
+    {   "check",
+        "?-clear? ?signals ...?",
+        signal_cmd_check,
+        0,
+        -1,
+        /* Description: Returns ignored signals which have occurred, and optionally clearing them */
     },
-    {   .cmd = "throw",
-        .args = "?signal?",
-        .function = signal_cmd_throw,
-        .minargs = 0,
-        .maxargs = 1,
-        .description = "Raises the given signal (default SIGINT)"
+    {   "throw",
+        "?signal?",
+        signal_cmd_throw,
+        0,
+        1,
+        /* Description: Raises the given signal (default SIGINT) */
     },
-    { 0 }
+    { NULL }
 };
 
 static int Jim_AlarmCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
@@ -437,12 +445,9 @@ static int Jim_SleepCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         ret = Jim_GetDouble(interp, argv[1], &t);
         if (ret == JIM_OK) {
 #ifdef HAVE_USLEEP
-            if (t < 1) {
-                usleep(t * 1e6);
-            }
-            else
+            usleep((int)((t - (int)t) * 1e6));
 #endif
-                sleep(t);
+            sleep(t);
         }
     }
 
@@ -462,22 +467,22 @@ static int Jim_KillCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
     }
 
     if (argc == 2) {
-        signame = "SIGTERM";
+        sig = SIGTERM;
         pidObj = argv[1];
     }
     else {
         signame = Jim_String(argv[1]);
         pidObj = argv[2];
-    }
 
-    /* Special 'kill -0 pid' to determine if a pid exists */
-    if (strcmp(signame, "-0") == 0 || strcmp(signame, "0") == 0) {
-        sig = 0;
-    }
-    else {
-        sig = find_signal_by_name(interp, signame);
-        if (sig < 0) {
-            return JIM_ERR;
+        /* Special 'kill -0 pid' to determine if a pid exists */
+        if (strcmp(signame, "-0") == 0 || strcmp(signame, "0") == 0) {
+            sig = 0;
+        }
+        else {
+            sig = find_signal_by_name(interp, signame);
+            if (sig < 0) {
+                return JIM_ERR;
+            }
         }
     }
 
@@ -498,6 +503,8 @@ int Jim_signalInit(Jim_Interp *interp)
     if (Jim_PackageProvide(interp, "signal", "1.0", JIM_ERRMSG))
         return JIM_ERR;
 
+    signal_init_names();
+
     /* Teach the jim core how to set a result from a sigmask */
     interp->signal_set_result = signal_set_sigmask_result;
 
index 92e080d..84dcd8b 100644 (file)
@@ -1,24 +1,26 @@
 #ifndef JIM_SIGNAL_H
 #define JIM_SIGNAL_H
 
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_SignalId --
- *
- *      Return a textual identifier for a signal number.
- *
- * Results:
- *      This procedure returns a machine-readable textual identifier
- *      that corresponds to sig.  The identifier is the same as the
- *      #define name in signal.h.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns the canonical name for the given signal,
+ * e.g. "SIGTERM", "SIGINT"
  */
 const char *Jim_SignalId(int sig);
+
+/**
+ * If available, returns a short description of the given signal.
+ * e.g. "Terminated", "Interrupted"
+ * 
+ * Otherwise returns the same as Jim_SignalId()
+ */
 const char *Jim_SignalName(int sig);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/jim/jim-sqlite3.c b/jim/jim-sqlite3.c
new file mode 100644 (file)
index 0000000..e5fa304
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Jim - Sqlite bindings
+ *
+ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sqlite3.h>
+
+#include <jim.h>
+
+static void JimSqliteDelProc(Jim_Interp *interp, void *privData)
+{
+    sqlite3 *db = privData;
+
+    JIM_NOTUSED(interp);
+
+    sqlite3_close(db);
+}
+
+static char *JimSqliteQuoteString(const char *str, int len, int *newLenPtr)
+{
+    int i, newLen, c = 0;
+    const char *s;
+    char *d, *buf;
+
+    for (i = 0; i < len; i++)
+        if (str[i] == '\'')
+            c++;
+    newLen = len + c;
+    s = str;
+    d = buf = Jim_Alloc(newLen);
+    while (len--) {
+        if (*s == '\'')
+            *d++ = '\'';
+        *d++ = *s++;
+    }
+    *newLenPtr = newLen;
+    return buf;
+}
+
+static Jim_Obj *JimSqliteFormatQuery(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
+    int objc, Jim_Obj *const *objv)
+{
+    const char *fmt;
+    int fmtLen;
+    Jim_Obj *resObjPtr;
+
+    fmt = Jim_GetString(fmtObjPtr, &fmtLen);
+    resObjPtr = Jim_NewStringObj(interp, "", 0);
+    while (fmtLen) {
+        const char *p = fmt;
+        char spec[2];
+
+        while (*fmt != '%' && fmtLen) {
+            fmt++;
+            fmtLen--;
+        }
+        Jim_AppendString(interp, resObjPtr, p, fmt - p);
+        if (fmtLen == 0)
+            break;
+        fmt++;
+        fmtLen--;               /* skip '%' */
+        if (*fmt != '%') {
+            if (objc == 0) {
+                Jim_FreeNewObj(interp, resObjPtr);
+                Jim_SetResultString(interp, "not enough arguments for all format specifiers", -1);
+                return NULL;
+            }
+            else {
+                objc--;
+            }
+        }
+        switch (*fmt) {
+            case 's':
+                {
+                    const char *str;
+                    char *quoted;
+                    int len, newLen;
+
+                    str = Jim_GetString(objv[0], &len);
+                    quoted = JimSqliteQuoteString(str, len, &newLen);
+                    Jim_AppendString(interp, resObjPtr, quoted, newLen);
+                    Jim_Free(quoted);
+                }
+                objv++;
+                break;
+            case '%':
+                Jim_AppendString(interp, resObjPtr, "%", 1);
+                break;
+            default:
+                spec[0] = *fmt;
+                spec[1] = '\0';
+                Jim_FreeNewObj(interp, resObjPtr);
+                Jim_SetResultFormatted(interp,
+                    "bad field specifier \"%s\", only %%s and %%%% are valid", spec);
+                return NULL;
+        }
+        fmt++;
+        fmtLen--;
+    }
+    return resObjPtr;
+}
+
+/* Calls to [sqlite.open] create commands that are implemented by this
+ * C command. */
+static int JimSqliteHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    sqlite3 *db = Jim_CmdPrivData(interp);
+    int option;
+    static const char * const options[] = {
+        "close", "query", "lastid", "changes", NULL
+    };
+    enum
+    { OPT_CLOSE, OPT_QUERY, OPT_LASTID, OPT_CHANGES };
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?");
+        return JIM_ERR;
+    }
+    if (Jim_GetEnum(interp, argv[1], options, &option, "Sqlite method", JIM_ERRMSG) != JIM_OK)
+        return JIM_ERR;
+    /* CLOSE */
+    if (option == OPT_CLOSE) {
+        if (argc != 2) {
+            Jim_WrongNumArgs(interp, 2, argv, "");
+            return JIM_ERR;
+        }
+        Jim_DeleteCommand(interp, Jim_String(argv[0]));
+        return JIM_OK;
+    }
+    else if (option == OPT_QUERY) {
+        /* QUERY */
+        Jim_Obj *objPtr, *rowsListPtr;
+        sqlite3_stmt *stmt;
+        const char *query, *tail;
+        int columns, rows, len;
+        int retcode = JIM_ERR;
+        Jim_Obj *nullStrObj;
+
+        if (argc >= 4 && Jim_CompareStringImmediate(interp, argv[2], "-null")) {
+            nullStrObj = argv[3];
+            argv += 2;
+            argc -= 2;
+        }
+        else {
+            nullStrObj = Jim_NewEmptyStringObj(interp);
+        }
+        Jim_IncrRefCount(nullStrObj);
+        if (argc < 3) {
+            Jim_WrongNumArgs(interp, 2, argv, "query ?args?");
+            goto err;
+        }
+        objPtr = JimSqliteFormatQuery(interp, argv[2], argc - 3, argv + 3);
+        if (objPtr == NULL) {
+            return JIM_ERR;
+        }
+        query = Jim_GetString(objPtr, &len);
+        Jim_IncrRefCount(objPtr);
+        /* Compile the query into VM code */
+        if (sqlite3_prepare_v2(db, query, len, &stmt, &tail) != SQLITE_OK) {
+            Jim_DecrRefCount(interp, objPtr);
+            Jim_SetResultString(interp, sqlite3_errmsg(db), -1);
+            goto err;
+        }
+        Jim_DecrRefCount(interp, objPtr);       /* query no longer needed. */
+        /* Build a list of rows (that are lists in turn) */
+        rowsListPtr = Jim_NewListObj(interp, NULL, 0);
+        Jim_IncrRefCount(rowsListPtr);
+        rows = 0;
+        columns = sqlite3_column_count(stmt);
+        while (sqlite3_step(stmt) == SQLITE_ROW) {
+            int i;
+
+            objPtr = Jim_NewListObj(interp, NULL, 0);
+            for (i = 0; i < columns; i++) {
+                Jim_Obj *vObj = NULL;
+
+                Jim_ListAppendElement(interp, objPtr,
+                    Jim_NewStringObj(interp, sqlite3_column_name(stmt, i), -1));
+                switch (sqlite3_column_type(stmt, i)) {
+                    case SQLITE_NULL:
+                        vObj = nullStrObj;
+                        break;
+                    case SQLITE_INTEGER:
+                        vObj = Jim_NewIntObj(interp, sqlite3_column_int(stmt, i));
+                        break;
+                    case SQLITE_FLOAT:
+                        vObj = Jim_NewDoubleObj(interp, sqlite3_column_double(stmt, i));
+                        break;
+                    case SQLITE_TEXT:
+                    case SQLITE_BLOB:
+                        vObj = Jim_NewStringObj(interp,
+                            sqlite3_column_blob(stmt, i), sqlite3_column_bytes(stmt, i));
+                        break;
+                }
+                Jim_ListAppendElement(interp, objPtr, vObj);
+            }
+            Jim_ListAppendElement(interp, rowsListPtr, objPtr);
+            rows++;
+        }
+        /* Finalize */
+        if (sqlite3_finalize(stmt) != SQLITE_OK) {
+            Jim_SetResultString(interp, sqlite3_errmsg(db), -1);
+        }
+        else {
+            Jim_SetResult(interp, rowsListPtr);
+            retcode = JIM_OK;
+        }
+        Jim_DecrRefCount(interp, rowsListPtr);
+err:
+        Jim_DecrRefCount(interp, nullStrObj);
+
+        return retcode;
+    }
+    else if (option == OPT_LASTID) {
+        if (argc != 2) {
+            Jim_WrongNumArgs(interp, 2, argv, "");
+            return JIM_ERR;
+        }
+        Jim_SetResult(interp, Jim_NewIntObj(interp, sqlite3_last_insert_rowid(db)));
+        return JIM_OK;
+    }
+    else if (option == OPT_CHANGES) {
+        if (argc != 2) {
+            Jim_WrongNumArgs(interp, 2, argv, "");
+            return JIM_ERR;
+        }
+        Jim_SetResult(interp, Jim_NewIntObj(interp, sqlite3_changes(db)));
+        return JIM_OK;
+    }
+    return JIM_OK;
+}
+
+static int JimSqliteOpenCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    sqlite3 *db;
+    char buf[60];
+    int r;
+
+    if (argc != 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "dbname");
+        return JIM_ERR;
+    }
+    r = sqlite3_open(Jim_String(argv[1]), &db);
+    if (r != SQLITE_OK) {
+        Jim_SetResultString(interp, sqlite3_errmsg(db), -1);
+        sqlite3_close(db);
+        return JIM_ERR;
+    }
+    /* Create the file command */
+    snprintf(buf, sizeof(buf), "sqlite.handle%ld", Jim_GetId(interp));
+    Jim_CreateCommand(interp, buf, JimSqliteHandlerCommand, db, JimSqliteDelProc);
+
+    Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
+
+    return JIM_OK;
+}
+
+int Jim_sqlite3Init(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "sqlite3", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+    Jim_CreateCommand(interp, "sqlite3.open", JimSqliteOpenCommand, NULL, NULL);
+    return JIM_OK;
+}
index 2de560a..c522830 100644 (file)
@@ -1,8 +1,14 @@
+/*
+ * Makes it easy to support "ensembles". i.e. commands with subcommands
+ * like [string] and [array]
+ *
+ * (c) 2008 Steve Bennett <steveb@workware.net.au>
+ *
+ */
 #include <stdio.h>
 #include <string.h>
 
-#include "jim-subcmd.h"
-#include "jimautoconf.h"
+#include <jim-subcmd.h>
 
 /**
  * Implements the common 'commands' subcommand
@@ -17,9 +23,7 @@ static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
  * Do-nothing command to support -commands and -usage
  */
 static const jim_subcmd_type dummy_subcmd = {
-    .cmd = "dummy",
-    .function = subcmd_null,
-    .flags = JIM_MODFLAG_HIDDEN,
+    "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN
 };
 
 static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep)
@@ -63,25 +67,9 @@ static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Ob
     }
 }
 
-static void show_full_usage(Jim_Interp *interp, const jim_subcmd_type * ct, int argc,
-    Jim_Obj *const *argv)
-{
-    Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-    for (; ct->cmd; ct++) {
-        if (!(ct->flags & JIM_MODFLAG_HIDDEN)) {
-            /* subcmd */
-            add_cmd_usage(interp, ct, argv[0]);
-            if (ct->description) {
-                Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n    ", ct->description, NULL);
-            }
-            Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", NULL);
-        }
-    }
-}
-
 static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd)
 {
-    Jim_SetResultString(interp, "wrong # args: must be \"", -1);
+    Jim_SetResultString(interp, "wrong # args: should be \"", -1);
     add_cmd_usage(interp, command_table, subcmd);
     Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
 }
@@ -103,19 +91,12 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
         Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
         Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname,
             " command ...\"\n", NULL);
-        Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help\" or \"",
-            cmdname, " -help command\" for help", NULL);
+        Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL);
         return 0;
     }
 
     cmd = argv[1];
 
-    if (argc == 2 && Jim_CompareStringImmediate(interp, cmd, "-usage")) {
-        /* Show full usage */
-        show_full_usage(interp, command_table, argc, argv);
-        return &dummy_subcmd;
-    }
-
     /* Check for the help command */
     if (Jim_CompareStringImmediate(interp, cmd, "-help")) {
         if (argc == 2) {
@@ -180,15 +161,12 @@ const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type
         Jim_SetResultString(interp, "Usage: ", -1);
         /* subcmd */
         add_cmd_usage(interp, ct, argv[0]);
-        if (ct->description) {
-            Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", ct->description, NULL);
-        }
         return &dummy_subcmd;
     }
 
     /* Check the number of args */
     if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) {
-        Jim_SetResultString(interp, "wrong # args: must be \"", -1);
+        Jim_SetResultString(interp, "wrong # args: should be \"", -1);
         /* subcmd */
         add_cmd_usage(interp, ct, argv[0]);
         Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL);
@@ -226,68 +204,3 @@ int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
     return Jim_CallSubCmd(interp, ct, argc, argv);
 }
-
-/* The following two functions are for normal commands */
-int
-Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc,
-    Jim_Obj *const *argv)
-{
-    /* -usage or -help */
-    if (argc == 2) {
-        if (Jim_CompareStringImmediate(interp, argv[1], "-usage")
-            || Jim_CompareStringImmediate(interp, argv[1], "-help")) {
-            Jim_SetResultString(interp, "Usage: ", -1);
-            add_cmd_usage(interp, command_table, NULL);
-            if (command_table->description) {
-                Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", command_table->description,
-                    NULL);
-            }
-            return JIM_OK;
-        }
-    }
-    if (argc >= 2 && command_table->function) {
-        /* This is actually a sub command table */
-
-        Jim_Obj *nargv[4];
-        int nargc = 0;
-        const char *subcmd = NULL;
-
-        if (Jim_CompareStringImmediate(interp, argv[1], "-subcommands")) {
-            Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-            add_commands(interp, (jim_subcmd_type *) command_table->function, " ");
-            return JIM_OK;
-        }
-
-        if (Jim_CompareStringImmediate(interp, argv[1], "-subhelp")
-            || Jim_CompareStringImmediate(interp, argv[1], "-help")) {
-            subcmd = "-help";
-        }
-        else if (Jim_CompareStringImmediate(interp, argv[1], "-subusage")) {
-            subcmd = "-usage";
-        }
-
-        if (subcmd) {
-            nargv[nargc++] = Jim_NewStringObj(interp, "$handle", -1);
-            nargv[nargc++] = Jim_NewStringObj(interp, subcmd, -1);
-            if (argc >= 3) {
-                nargv[nargc++] = argv[2];
-            }
-            Jim_ParseSubCmd(interp, (jim_subcmd_type *) command_table->function, nargc, nargv);
-            Jim_FreeNewObj(interp, nargv[0]);
-            Jim_FreeNewObj(interp, nargv[1]);
-            return 0;
-        }
-    }
-
-    /* Check the number of args */
-    if (argc - 1 < command_table->minargs || (command_table->maxargs >= 0
-            && argc - 1 > command_table->maxargs)) {
-        set_wrong_args(interp, command_table, NULL);
-        Jim_AppendStrings(interp, Jim_GetResult(interp), "\nUse \"", Jim_String(argv[0]),
-            " -help\" for help", NULL);
-        return JIM_ERR;
-    }
-
-    /* Not usage, but passed arg checking */
-    return -1;
-}
index 3a672eb..ab30f37 100644 (file)
@@ -20,16 +20,15 @@ extern "C" {
  * Returns JIM_OK if OK, JIM_ERR (etc.) on error, break, continue, etc.
  * Returns -1 if invalid args.
  */
-typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
 
 typedef struct {
        const char *cmd;                                /* Name of the (sub)command */
        const char *args;                               /* Textual description of allowed args */
-       tclmod_cmd_function *function;  /* Function implementing the subcommand */
+       jim_subcmd_function *function;  /* Function implementing the subcommand */
        short minargs;                                  /* Minimum required arguments */
        short maxargs;                                  /* Maximum allowed arguments or -1 if no limit */
-       unsigned flags;                                 /* JIM_MODFLAG_... plus custom flags */
-       const char *description;                /* Description of the subcommand */
+       unsigned short flags;                   /* JIM_MODFLAG_... plus custom flags */
 } jim_subcmd_type;
 
 /**
@@ -71,20 +70,6 @@ int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
  */
 int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv);
 
-/**
- * Standard processing for a command.
- *
- * This does the '-help' and '-usage' check and the number of args checks.
- * for a top level command against a single 'jim_subcmd_type' structure.
- *
- * Additionally, if command_table->function is set, it should point to a sub command table
- * and '-subhelp ?subcmd?', '-subusage' and '-subcommands' are then also recognised.
- *
- * Returns 0 if user requested usage, -1 on arg error, 1 if OK to process.
- */
-int
-Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv);
-
 #ifdef __cplusplus
 }
 #endif
index 4e14910..9e279ef 100644 (file)
@@ -1,4 +1,3 @@
-
 /* Syslog interface for tcl
  * Copyright Victor Wagner <vitus@ice.ru> at
  * http://www.ice.ru/~vitus/works/tcl.html#syslog
@@ -9,8 +8,7 @@
 #include <syslog.h>
 #include <string.h>
 
-#include "jim.h"
-#include "jimautoconf.h"
+#include <jim.h>
 
 typedef struct
 {
diff --git a/jim/jim-tclprefix.c b/jim/jim-tclprefix.c
new file mode 100644 (file)
index 0000000..e041cc6
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Implements the tcl::prefix command for Jim Tcl
+ *
+ * (c) 2011 Steve Bennett <steveb@workware.net.au>
+ *
+ * See LICENSE for license details.
+ */
+
+#include <jim.h>
+#include "utf8.h"
+
+/**
+ * Returns the common initial length of the two strings.
+ */
+static int JimStringCommonLength(const char *str1, int charlen1, const char *str2, int charlen2)
+{
+    int maxlen = 0;
+    while (charlen1-- && charlen2--) {
+        int c1;
+        int c2;
+        str1 += utf8_tounicode(str1, &c1);
+        str2 += utf8_tounicode(str2, &c2);
+        if (c1 != c2) {
+            break;
+        }
+        maxlen++;
+    }
+    return maxlen;
+}
+
+/* [tcl::prefix]
+ */
+static int Jim_TclPrefixCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *objPtr;
+    Jim_Obj *stringObj;
+    int option;
+    static const char * const options[] = { "match", "all", "longest", NULL };
+    enum { OPT_MATCH, OPT_ALL, OPT_LONGEST };
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arg ...?");
+        return JIM_ERR;
+    }
+    if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
+        return JIM_ERR;
+
+    switch (option) {
+        case OPT_MATCH:{
+            int i;
+            int ret;
+            int tablesize;
+            const char **table;
+            Jim_Obj *tableObj;
+            Jim_Obj *errorObj = NULL;
+            Jim_Obj *messageObj = NULL;
+            static const char * const matchoptions[] = { "-error", "-exact", "-message", NULL };
+            enum { OPT_MATCH_ERROR, OPT_MATCH_EXACT, OPT_MATCH_MESSAGE };
+            int flags = JIM_ERRMSG | JIM_ENUM_ABBREV;
+
+            if (argc < 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "?options? table string");
+                return JIM_ERR;
+            }
+            tableObj = argv[argc - 2];
+            stringObj = argv[argc - 1];
+            argc -= 2;
+            for (i = 2; i < argc; i++) {
+                int matchoption;
+                if (Jim_GetEnum(interp, argv[i], matchoptions, &matchoption, "option", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
+                    return JIM_ERR;
+                switch (matchoption) {
+                    case OPT_MATCH_EXACT:
+                        flags &= ~JIM_ENUM_ABBREV;
+                        break;
+
+                    case OPT_MATCH_ERROR:
+                        if (++i == argc) {
+                            Jim_SetResultString(interp, "missing error options", -1);
+                            return JIM_ERR;
+                        }
+                        errorObj = argv[i];
+                        if (Jim_Length(errorObj) % 2) {
+                            Jim_SetResultString(interp, "error options must have an even number of elements", -1);
+                            return JIM_ERR;
+                        }
+                        break;
+
+                    case OPT_MATCH_MESSAGE:
+                        if (++i == argc) {
+                            Jim_SetResultString(interp, "missing message", -1);
+                            return JIM_ERR;
+                        }
+                        messageObj = argv[i];
+                        break;
+                }
+            }
+            /* Do the match */
+            tablesize = Jim_ListLength(interp, tableObj);
+            table = Jim_Alloc((tablesize + 1) * sizeof(*table));
+            for (i = 0; i < tablesize; i++) {
+                Jim_ListIndex(interp, tableObj, i, &objPtr, JIM_NONE);
+                table[i] = Jim_String(objPtr);
+            }
+            table[i] = NULL;
+
+            ret = Jim_GetEnum(interp, stringObj, table, &i, messageObj ? Jim_String(messageObj) : NULL, flags);
+            Jim_Free(table);
+            if (ret == JIM_OK) {
+                Jim_ListIndex(interp, tableObj, i, &objPtr, JIM_NONE);
+                Jim_SetResult(interp, objPtr);
+                return JIM_OK;
+            }
+            if (tablesize == 0) {
+                Jim_SetResultFormatted(interp, "bad option \"%#s\": no valid options", stringObj);
+                return JIM_ERR;
+            }
+            if (errorObj) {
+                if (Jim_Length(errorObj) == 0) {
+                    Jim_SetEmptyResult(interp);
+                    return JIM_OK;
+                }
+                /* Do this the easy way. Build a list to evaluate */
+                objPtr = Jim_NewStringObj(interp, "return -level 0 -code error", -1);
+                Jim_ListAppendList(interp, objPtr, errorObj);
+                Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
+                return Jim_EvalObjList(interp, objPtr);
+            }
+            return JIM_ERR;
+        }
+        break;
+
+        case OPT_ALL:
+            if (argc != 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "table string");
+                return JIM_ERR;
+            }
+            else {
+                int i;
+                int listlen = Jim_ListLength(interp, argv[2]);
+                objPtr = Jim_NewListObj(interp, NULL, 0);
+                for (i = 0; i < listlen; i++) {
+                    Jim_Obj *valObj = Jim_ListGetIndex(interp, argv[2], i);
+                    if (Jim_StringCompareLenObj(interp, argv[3], valObj, 0) == 0) {
+                        Jim_ListAppendElement(interp, objPtr, valObj);
+                    }
+                }
+                Jim_SetResult(interp, objPtr);
+                return JIM_OK;
+            }
+
+        case OPT_LONGEST:
+            if (argc != 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "table string");
+                return JIM_ERR;
+            }
+            else if (Jim_ListLength(interp, argv[2])) {
+                const char *longeststr = NULL;
+                int longestlen = 0;
+
+                stringObj = argv[3];
+
+                int i;
+                int listlen = Jim_ListLength(interp, argv[2]);
+                for (i = 0; i < listlen; i++) {
+                    Jim_Obj *valObj = Jim_ListGetIndex(interp, argv[2], i);
+
+                    if (Jim_StringCompareLenObj(interp, stringObj, valObj, 0)) {
+                        /* Does not begin with 'string' */
+                        continue;
+                    }
+
+                    if (longeststr == NULL) {
+                        longestlen = Jim_Utf8Length(interp, valObj);
+                        longeststr = Jim_String(valObj);
+                    }
+                    else {
+                        longestlen = JimStringCommonLength(longeststr, longestlen, Jim_String(valObj), Jim_Utf8Length(interp, valObj));
+                    }
+                }
+                if (longeststr) {
+                    Jim_SetResultString(interp, longeststr, longestlen);
+                }
+                return JIM_OK;
+            }
+    }
+    return JIM_ERR;
+}
+
+int Jim_tclprefixInit(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "tclprefix", "1.0", JIM_ERRMSG)) {
+        return JIM_ERR;
+    }
+
+    Jim_CreateCommand(interp, "tcl::prefix", Jim_TclPrefixCoreCommand, NULL, NULL);
+    return JIM_OK;
+}
diff --git a/jim/jim-win32.c b/jim/jim-win32.c
new file mode 100644 (file)
index 0000000..89cedd4
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * WIN32 extension
+ *
+ * Copyright (C) 2005 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
+ */
+
+#include <jim.h>
+
+/* Apparently windows.h and cygwin don't mix, but we seem to get
+ * away with it here. Use at your own risk under cygwin
+ */
+#if defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include <shellapi.h>
+#include <lmcons.h>
+#include <psapi.h>
+#include <ctype.h>
+
+#if _MSC_VER >= 1000
+#pragma comment(lib, "shell32")
+#pragma comment(lib, "user32")
+#pragma comment(lib, "advapi32")
+#pragma comment(lib, "psapi")
+#endif /* _MSC_VER >= 1000 */
+
+static Jim_Obj *
+Win32ErrorObj(Jim_Interp *interp, const char * szPrefix, DWORD dwError)
+{
+    Jim_Obj *msgObj = NULL;
+    char * lpBuffer = NULL;
+    DWORD  dwLen = 0;
+
+    dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
+        | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, LANG_NEUTRAL,
+        (char *)&lpBuffer, 0, NULL);
+    if (dwLen < 1) {
+        dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
+            | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+            "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
+            (char *)&lpBuffer, 0, (va_list *)&dwError);
+    }
+
+    msgObj = Jim_NewStringObj(interp, szPrefix, -1);
+    if (dwLen > 0) {
+        char *p = lpBuffer + dwLen - 1;        /* remove cr-lf at end */
+        for ( ; p && *p && isspace(UCHAR(*p)); p--)
+            ;
+        *++p = 0;
+        Jim_AppendString(interp, msgObj, ": ", 2);
+        Jim_AppendString(interp, msgObj, lpBuffer, -1);
+    }
+    LocalFree((HLOCAL)lpBuffer);
+    return msgObj;
+}
+
+/* win32.ShellExecute verb file args */
+static int
+Win32_ShellExecute(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    int r;
+    const char *verb, *file, *parm = NULL;
+    char cwd[MAX_PATH + 1];
+
+    if (objc < 3 || objc > 4) {
+        Jim_WrongNumArgs(interp, 1, objv, "verb path ?parameters?");
+        return JIM_ERR;
+    }
+    verb = Jim_String(objv[1]);
+    file = Jim_String(objv[2]);
+    GetCurrentDirectoryA(MAX_PATH + 1, cwd);
+    if (objc == 4)
+        parm = Jim_String(objv[3]);
+    r = (int)ShellExecuteA(NULL, verb, file, parm, cwd, SW_SHOWNORMAL);
+    if (r < 33)
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "ShellExecute", GetLastError()));
+    return (r < 33) ? JIM_ERR : JIM_OK;
+}
+
+
+/* win32.FindWindow title ?class? */
+static int
+Win32_FindWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    const char *title = NULL, *class = NULL;
+    HWND hwnd = NULL;
+    int r = JIM_OK;
+
+    if (objc < 2 || objc > 3) {
+        Jim_WrongNumArgs(interp, 1, objv, "title ?class?");
+        return JIM_ERR;
+    }
+    title = Jim_String(objv[1]);
+    if (objc == 3)
+        class = Jim_String(objv[2]);
+    hwnd = FindWindowA(class, title);
+
+    if (hwnd == NULL) {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "FindWindow", GetLastError()));
+        r = JIM_ERR;
+    } else {
+        Jim_SetResult(interp, Jim_NewIntObj(interp, (long)hwnd));
+    }
+    return r;
+}
+
+/* win32.CloseWindow windowHandle */
+static int
+Win32_CloseWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    long hwnd;
+
+    if (objc != 2) {
+        Jim_WrongNumArgs(interp, 1, objv, "?windowHandle?");
+        return JIM_ERR;
+    }
+    if (Jim_GetLong(interp, objv[1], &hwnd) != JIM_OK)
+        return JIM_ERR;
+    if (!CloseWindow((HWND)hwnd)) {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "CloseWindow", GetLastError()));
+        return JIM_ERR;
+    }
+    return JIM_OK;
+}
+
+static int
+Win32_GetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    Jim_SetResult(interp, Jim_NewIntObj(interp, (DWORD)GetActiveWindow()));
+    return JIM_OK;
+}
+
+static int
+Win32_SetActiveWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    HWND hwnd, old;
+    int r = JIM_OK;
+
+    if (objc != 2) {
+        Jim_WrongNumArgs(interp, 1, objv, "windowHandle");
+        return JIM_ERR;
+    }
+    r = Jim_GetLong(interp, objv[1], (long *)&hwnd);
+    if (r == JIM_OK) {
+        old = SetActiveWindow(hwnd);
+        if (old == NULL) {
+            Jim_SetResult(interp,
+                Win32ErrorObj(interp, "SetActiveWindow", GetLastError()));
+            r = JIM_ERR;
+        } else {
+            Jim_SetResult(interp, Jim_NewIntObj(interp, (long)old));
+        }
+    }
+    return r;
+}
+
+static int
+Win32_SetForegroundWindow(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    HWND hwnd;
+    int r = JIM_OK;
+
+    if (objc != 2) {
+        Jim_WrongNumArgs(interp, 1, objv, "windowHandle");
+        return JIM_ERR;
+    }
+    r = Jim_GetLong(interp, objv[1], (long *)&hwnd);
+    if (r == JIM_OK) {
+        if (!SetForegroundWindow(hwnd)) {
+            Jim_SetResult(interp,
+                Win32ErrorObj(interp, "SetForegroundWindow", GetLastError()));
+            r = JIM_ERR;
+        }
+    }
+    return r;
+}
+
+static int
+Win32_Beep(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    long freq, duration;
+    int r = JIM_OK;
+
+    if (objc != 3) {
+        Jim_WrongNumArgs(interp, 1, objv, "freq duration");
+        return JIM_ERR;
+    }
+    r = Jim_GetLong(interp, objv[1], &freq);
+    if (r == JIM_OK)
+        r = Jim_GetLong(interp, objv[2], &duration);
+    if (freq < 0x25) freq = 0x25;
+    if (freq > 0x7fff) freq = 0x7fff;
+    if (r == JIM_OK) {
+        if (!Beep(freq, duration)) {
+            Jim_SetResult(interp,
+                Win32ErrorObj(interp, "Beep", GetLastError()));
+            r = JIM_ERR;
+        }
+    }
+    return r;
+}
+
+static int
+Win32_GetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    char name[MAX_COMPUTERNAME_LENGTH + 1];
+    DWORD size = MAX_COMPUTERNAME_LENGTH;
+    int r = JIM_OK;
+
+    if (objc != 1) {
+        Jim_WrongNumArgs(interp, 1, objv, "");
+        return JIM_ERR;
+    }
+
+    if (GetComputerNameA(name, &size)) {
+        Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size);
+        Jim_SetResult(interp, nameObj);
+    } else {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "GetComputerName", GetLastError()));
+        r = JIM_ERR;
+    }
+
+    return r;
+}
+
+static int
+Win32_GetUserName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    char name[UNLEN + 1];
+    DWORD size = UNLEN;
+    int r = JIM_OK;
+
+    if (objc != 1) {
+        Jim_WrongNumArgs(interp, 1, objv, "");
+        return JIM_ERR;
+    }
+
+    if (GetUserNameA(name, &size)) {
+        Jim_Obj *nameObj = Jim_NewStringObj(interp, name, size);
+        Jim_SetResult(interp, nameObj);
+    } else {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "GetUserName", GetLastError()));
+        r = JIM_ERR;
+    }
+
+    return r;
+}
+
+static int
+Win32_GetModuleFileName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    HMODULE hModule = NULL;
+    char path[MAX_PATH];
+    DWORD len = 0;
+
+    if (objc > 2) {
+        Jim_WrongNumArgs(interp, 1, objv, "?moduleid?");
+        return JIM_ERR;
+    }
+
+    if (objc == 2) {
+        if (Jim_GetLong(interp, objv[1], (long *)&hModule) != JIM_OK) {
+            return JIM_ERR;
+        }
+    }
+
+    len = GetModuleFileNameA(hModule, path, MAX_PATH);
+    if (len != 0) {
+        Jim_Obj *pathObj = Jim_NewStringObj(interp, path, len);
+        Jim_SetResult(interp, pathObj);
+    } else {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "GetModuleFileName", GetLastError()));
+        return JIM_ERR;
+    }
+
+    return JIM_OK;
+}
+
+static int
+Win32_GetVersion(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    Jim_SetResult(interp, Jim_NewIntObj(interp, GetVersion()));
+    return JIM_OK;
+}
+
+static int
+Win32_GetTickCount(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    Jim_SetResult(interp, Jim_NewIntObj(interp, GetTickCount()));
+    return JIM_OK;
+}
+
+static int
+Win32_GetSystemTime(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    Jim_Obj *a[16];
+    size_t n = 0;
+    SYSTEMTIME t;
+    GetSystemTime(&t);
+
+#define JIMADD(name) \
+    a[n++] = Jim_NewStringObj(interp, #name, -1); \
+    a[n++] = Jim_NewIntObj(interp, t.w ## name )
+
+    JIMADD(Year);
+    JIMADD(Month);
+    JIMADD(DayOfWeek);
+    JIMADD(Day);
+    JIMADD(Hour);
+    JIMADD(Minute);
+    JIMADD(Second);
+    JIMADD(Milliseconds);
+#undef JIMADD
+
+    Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
+    return JIM_OK;
+}
+
+/* function not available on mingw or cygwin */
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+// FIX ME: win2k+ so should do version checks really.
+static int
+Win32_GetPerformanceInfo(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    Jim_Obj *a[26];
+    size_t n = 0;
+    PERFORMANCE_INFORMATION pi;
+
+    if (!GetPerformanceInfo(&pi, sizeof(pi))) {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "GetPerformanceInfo", GetLastError()));
+        return JIM_ERR;
+    }
+
+#define JIMADD(name) \
+    a[n++] = Jim_NewStringObj(interp, #name, -1); \
+    a[n++] = Jim_NewIntObj(interp, pi. name )
+
+    JIMADD(CommitTotal);
+    JIMADD(CommitLimit);
+    JIMADD(CommitPeak);
+    JIMADD(PhysicalTotal);
+    JIMADD(PhysicalAvailable);
+    JIMADD(SystemCache);
+    JIMADD(KernelTotal);
+    JIMADD(KernelPaged);
+    JIMADD(KernelNonpaged);
+    JIMADD(PageSize);
+    JIMADD(HandleCount);
+    JIMADD(ProcessCount);
+    JIMADD(ThreadCount);
+#undef JIMADD
+
+    Jim_SetResult(interp, Jim_NewListObj(interp, a, n));
+    return JIM_OK;
+}
+#endif
+
+static int
+Win32_SetComputerName(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    int r = JIM_OK;
+    const char *name;
+    if (objc != 2) {
+        Jim_WrongNumArgs(interp, 1, objv, "computername");
+        return JIM_ERR;
+    }
+    name = Jim_String(objv[1]);
+    if (!SetComputerNameA(name)) {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "SetComputerName", GetLastError()));
+        r = JIM_ERR;
+    }
+    return r;
+}
+
+static int
+Win32_GetModuleHandle(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    HMODULE hModule = NULL;
+    const char *name = NULL;
+
+    if (objc < 1 || objc >  2) {
+        Jim_WrongNumArgs(interp, 1, objv, "?name?");
+        return JIM_ERR;
+    }
+    if (objc == 2)
+        name = Jim_String(objv[1]);
+    hModule = GetModuleHandleA(name);
+    if (hModule == NULL) {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "GetModuleHandle", GetLastError()));
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hModule));
+    return JIM_OK;
+}
+
+static int
+Win32_LoadLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    HMODULE hLib = NULL;
+    if (objc != 2) {
+        Jim_WrongNumArgs(interp, 1, objv, "path");
+        return JIM_ERR;
+    }
+    hLib = LoadLibraryA(Jim_String(objv[1]));
+    if (hLib == NULL) {
+        Jim_SetResult(interp,
+            Win32ErrorObj(interp, "LoadLibrary", GetLastError()));
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, Jim_NewIntObj(interp, (unsigned long)hLib));
+    return JIM_OK;
+}
+
+static int
+Win32_FreeLibrary(Jim_Interp *interp, int objc, Jim_Obj * const *objv)
+{
+    HMODULE hModule = NULL;
+    int r = JIM_OK;
+
+    if (objc != 2) {
+        Jim_WrongNumArgs(interp, 1, objv, "hmodule");
+        return JIM_ERR;
+    }
+
+    r = Jim_GetLong(interp, objv[1], (long *)&hModule);
+    if (r == JIM_OK) {
+        if (!FreeLibrary(hModule)) {
+            Jim_SetResult(interp,
+                Win32ErrorObj(interp, "FreeLibrary", GetLastError()));
+            r = JIM_ERR;
+        }
+    }
+
+    return r;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+Jim_win32Init(Jim_Interp *interp)
+{
+    if (Jim_PackageProvide(interp, "win32", "1.0", JIM_ERRMSG))
+        return JIM_ERR;
+
+#define CMD(name) \
+    Jim_CreateCommand(interp, "win32." #name , Win32_ ## name , NULL, NULL)
+
+    CMD(ShellExecute);
+    CMD(FindWindow);
+    CMD(CloseWindow);
+    CMD(GetActiveWindow);
+    CMD(SetActiveWindow);
+    CMD(SetForegroundWindow);
+    CMD(Beep);
+    CMD(GetComputerName);
+    CMD(SetComputerName);
+    CMD(GetUserName);
+    CMD(GetModuleFileName);
+    CMD(GetVersion);
+    CMD(GetTickCount);
+    CMD(GetSystemTime);
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+    CMD(GetPerformanceInfo);
+#endif
+    CMD(GetModuleHandle);
+    CMD(LoadLibrary);
+    CMD(FreeLibrary);
+
+    return JIM_OK;
+}
diff --git a/jim/jim-win32compat.c b/jim/jim-win32compat.c
new file mode 100644 (file)
index 0000000..94bd831
--- /dev/null
@@ -0,0 +1,132 @@
+#include "jim.h"
+#include "jimautoconf.h"
+
+#if defined(_WIN32) || defined(WIN32)
+#ifndef STRICT
+#define STRICT
+#endif
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#if defined(HAVE_DLOPEN_COMPAT)
+void *dlopen(const char *path, int mode)
+{
+    JIM_NOTUSED(mode);
+
+    return (void *)LoadLibraryA(path);
+}
+
+int dlclose(void *handle)
+{
+    FreeLibrary((HANDLE)handle);
+    return 0;
+}
+
+void *dlsym(void *handle, const char *symbol)
+{
+    return GetProcAddress((HMODULE)handle, symbol);
+}
+
+char *dlerror(void)
+{
+    static char msg[121];
+    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+                   LANG_NEUTRAL, msg, sizeof(msg) - 1, NULL);
+    return msg;
+}
+#endif
+
+#ifdef _MSC_VER
+
+#include <sys/timeb.h>
+
+/* POSIX gettimeofday() compatibility for WIN32 */
+int gettimeofday(struct timeval *tv, void *unused)
+{
+    struct _timeb tb;
+
+    _ftime(&tb);
+    tv->tv_sec = tb.time;
+    tv->tv_usec = tb.millitm * 1000;
+
+    return 0;
+}
+
+/* Posix dirent.h compatiblity layer for WIN32.
+ * Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+ * Copyright Salvatore Sanfilippo ,2005.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose is hereby granted without fee, provided
+ * that this copyright and permissions notice appear in all copies and
+ * derivatives.
+ *
+ * This software is supplied "as is" without express or implied warranty.
+ * This software was modified by Salvatore Sanfilippo for the Jim Interpreter.
+ */
+
+DIR *opendir(const char *name)
+{
+    DIR *dir = 0;
+
+    if (name && name[0]) {
+        size_t base_length = strlen(name);
+        const char *all =       /* search pattern must end with suitable wildcard */
+            strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+        if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 &&
+            (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) {
+            strcat(strcpy(dir->name, name), all);
+
+            if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1)
+                dir->result.d_name = 0;
+            else {              /* rollback */
+                Jim_Free(dir->name);
+                Jim_Free(dir);
+                dir = 0;
+            }
+        }
+        else {                  /* rollback */
+            Jim_Free(dir);
+            dir = 0;
+            errno = ENOMEM;
+        }
+    }
+    else {
+        errno = EINVAL;
+    }
+    return dir;
+}
+
+int closedir(DIR * dir)
+{
+    int result = -1;
+
+    if (dir) {
+        if (dir->handle != -1)
+            result = _findclose(dir->handle);
+        Jim_Free(dir->name);
+        Jim_Free(dir);
+    }
+    if (result == -1)           /* map all errors to EBADF */
+        errno = EBADF;
+    return result;
+}
+
+struct dirent *readdir(DIR * dir)
+{
+    struct dirent *result = 0;
+
+    if (dir && dir->handle != -1) {
+        if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) {
+            result = &dir->result;
+            result->d_name = dir->info.name;
+        }
+    }
+    else {
+        errno = EBADF;
+    }
+    return result;
+}
+#endif
+#endif
index 89e01f5..23a3dfe 100644 (file)
@@ -3,13 +3,12 @@
 
 /* Compatibility for Windows (mingw and msvc, not cygwin */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Note that at this point we don't yet have access to jimautoconf.h */
 #if defined(_WIN32) || defined(WIN32)
-#ifndef STRICT
-       #define STRICT
-#endif
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
 
 #define HAVE_DLOPEN
 void *dlopen(const char *path, int mode);
@@ -17,6 +16,9 @@ int dlclose(void *handle);
 void *dlsym(void *handle, const char *symbol);
 char *dlerror(void);
 
+/* MS CRT always uses three digits after 'e' */
+#define JIM_SPRINTF_DOUBLE_NEEDS_FIX
+
 #ifdef _MSC_VER
 /* These are msvc vs gcc */
 
@@ -24,8 +26,7 @@ char *dlerror(void);
        #pragma warning(disable:4146)
 #endif
 
-#define strcasecmp _stricmp
-
+#include <limits.h>
 #define jim_wide _int64
 #ifndef LLONG_MAX
        #define LLONG_MAX    9223372036854775807I64
@@ -36,10 +37,12 @@ char *dlerror(void);
 #define JIM_WIDE_MIN LLONG_MIN
 #define JIM_WIDE_MAX LLONG_MAX
 #define JIM_WIDE_MODIFIER "I64d"
+#define strcasecmp _stricmp
+#define strtoull _strtoui64
+#define snprintf _snprintf
 
 #include <io.h>
 
-#define HAVE_GETTIMEOFDAY
 struct timeval {
        long tv_sec;
        long tv_usec;
@@ -62,8 +65,17 @@ typedef struct DIR {
 DIR *opendir(const char *name);
 int closedir(DIR *dir);
 struct dirent *readdir(DIR *dir);
-#endif /* _MSC_VER */
+
+#elif defined(__MINGW32__)
+
+#define strtod __strtod
+
+#endif
 
 #endif /* WIN32 */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index 8543de4..76a192e 100644 (file)
--- a/jim/jim.c
+++ b/jim/jim.c
@@ -1,4 +1,3 @@
-
 /* Jim - A small embeddable Tcl interpreter
  *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
 #include <time.h>
 #include <setjmp.h>
 
-#include <unistd.h>
-#include <sys/time.h>
-
 #include "jim.h"
 #include "jimautoconf.h"
 #include "utf8.h"
 
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
 #ifdef HAVE_BACKTRACE
 #include <execinfo.h>
 #endif
 #define JIM_DEBUG_COMMAND
 #define JIM_DEBUG_PANIC
 #endif
+/* Enable this (in conjunction with valgrind) to help debug
+ * reference counting issues
+ */
+/*#define JIM_DISABLE_OBJECT_POOL*/
+
+/* Maximum size of an integer */
+#define JIM_INTEGER_SPACE 24
 
 const char *jim_tt_name(int type);
 
 #ifdef JIM_DEBUG_PANIC
-static void JimPanicDump(int panic_condition, const char *fmt, ...);
+static void JimPanicDump(int fail_condition, const char *fmt, ...);
 #define JimPanic(X) JimPanicDump X
 #else
 #define JimPanic(X)
@@ -120,19 +126,16 @@ static char JimEmptyStringRep[] = "";
 /* -----------------------------------------------------------------------------
  * Required prototypes of not exported functions
  * ---------------------------------------------------------------------------*/
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action);
 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
     int flags);
+static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
+static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
     const char *prefix, const char *const *tablePtr, const char *name);
-static void JimDeleteLocalProcs(Jim_Interp *interp);
-static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr,
-    int argc, Jim_Obj *const *argv);
-static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
-    Jim_Obj *fileNameObj, int linenr);
+static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
 static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
 static int JimSign(jim_wide w);
 static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr);
@@ -140,8 +143,6 @@ static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen);
 static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len);
 
 
-static const Jim_HashTableType JimVariablesHashTableType;
-
 /* Fast access to the int (wide) value of an object which is known to be of int type */
 #define JimWideValue(objPtr) (objPtr)->internalRep.wideValue
 
@@ -240,9 +241,8 @@ first:
 /* Glob-style pattern matching. */
 
 /* Note: string *must* be valid UTF-8 sequences
- *       slen is a char length, not byte counts.
  */
-static int GlobMatch(const char *pattern, const char *string, int nocase)
+static int JimGlobMatch(const char *pattern, const char *string, int nocase)
 {
     int c;
     int pchar;
@@ -258,7 +258,7 @@ static int GlobMatch(const char *pattern, const char *string, int nocase)
                 }
                 while (*string) {
                     /* Recursive call - Does the remaining pattern match anywhere? */
-                    if (GlobMatch(pattern, string, nocase))
+                    if (JimGlobMatch(pattern, string, nocase))
                         return 1;       /* match */
                     string += utf8_tounicode(string, &c);
                 }
@@ -307,13 +307,10 @@ static int GlobMatch(const char *pattern, const char *string, int nocase)
     return 0;
 }
 
-static int JimStringMatch(Jim_Interp *interp, Jim_Obj *patternObj, const char *string, int nocase)
-{
-    return GlobMatch(Jim_String(patternObj), string, nocase);
-}
-
 /**
- * string comparison works on binary data.
+ * string comparison. Works on binary data.
+ *
+ * Returns -1, 0 or 1
  *
  * Note that the lengths are byte lengths, not char lengths.
  */
@@ -331,17 +328,19 @@ static int JimStringCompare(const char *s1, int l1, const char *s2, int l2)
 }
 
 /**
- * No-case version.
+ * Compare null terminated strings, up to a maximum of 'maxchars' characters,
+ * (or end of string if 'maxchars' is -1).
+ *
+ * Returns -1, 0, 1 for s1 < s2, s1 == s2, s1 > s2 respectively.
  *
- * If maxchars is -1, compares to end of string.
- * Otherwise compares at most 'maxchars' characters.
+ * Note: does not support embedded nulls.
  */
-static int JimStringCompareNoCase(const char *s1, const char *s2, int maxchars)
+static int JimStringCompareLen(const char *s1, const char *s2, int maxchars, int nocase)
 {
     while (*s1 && *s2 && maxchars) {
         int c1, c2;
-        s1 += utf8_tounicode_case(s1, &c1, 1);
-        s2 += utf8_tounicode_case(s2, &c2, 1);
+        s1 += utf8_tounicode_case(s1, &c1, nocase);
+        s2 += utf8_tounicode_case(s2, &c2, nocase);
         if (c1 != c2) {
             return JimSign(c1 - c2);
         }
@@ -420,13 +419,6 @@ static int JimStringLastUtf8(const char *s1, int l1, const char *s2, int l2)
 }
 #endif
 
-int Jim_WideToString(char *buf, jim_wide wideValue)
-{
-    const char *fmt = "%" JIM_WIDE_MODIFIER;
-
-    return sprintf(buf, fmt, wideValue);
-}
-
 /**
  * After an strtol()/strtod()-like conversion,
  * check whether something was converted and that
@@ -451,45 +443,110 @@ static int JimCheckConversion(const char *str, const char *endptr)
     return JIM_OK;
 }
 
-int Jim_StringToWide(const char *str, jim_wide * widePtr, int base)
+/* Parses the front of a number to determine it's sign and base
+ * Returns the index to start parsing according to the given base
+ */
+static int JimNumberBase(const char *str, int *base, int *sign)
 {
-    char *endptr;
+    int i = 0;
 
-    *widePtr = strtoull(str, &endptr, base);
+    *base = 10;
 
-    return JimCheckConversion(str, endptr);
+    while (isspace(UCHAR(str[i]))) {
+        i++;
+    }
+
+    if (str[i] == '-') {
+        *sign = -1;
+        i++;
+    }
+    else {
+        if (str[i] == '+') {
+            i++;
+        }
+        *sign = 1;
+    }
+
+    if (str[i] != '0') {
+        /* base 10 */
+        return 0;
+    }
+
+    /* We have 0<x>, so see if we can convert it */
+    switch (str[i + 1]) {
+        case 'x': case 'X': *base = 16; break;
+        case 'o': case 'O': *base = 8; break;
+        case 'b': case 'B': *base = 2; break;
+        default: return 0;
+    }
+    i += 2;
+    /* Ensure that (e.g.) 0x-5 fails to parse */
+    if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) {
+        /* Parse according to this base */
+        return i;
+    }
+    /* Parse as base 10 */
+    *base = 10;
+    return 0;
 }
 
-int Jim_DoubleToString(char *buf, double doubleValue)
+/* Converts a number as per strtol(..., 0) except leading zeros do *not*
+ * imply octal. Instead, decimal is assumed unless the number begins with 0x, 0o or 0b
+ */
+static long jim_strtol(const char *str, char **endptr)
 {
-    int len;
-    char *buf0 = buf;
+    int sign;
+    int base;
+    int i = JimNumberBase(str, &base, &sign);
 
-    len = sprintf(buf, "%.12g", doubleValue);
+    if (base != 10) {
+        long value = strtol(str + i, endptr, base);
+        if (endptr == NULL || *endptr != str + i) {
+            return value * sign;
+        }
+    }
 
-    /* Add a final ".0" if it's a number. But not
-     * for NaN or InF */
-    while (*buf) {
-        if (*buf == '.' || isalpha(UCHAR(*buf))) {
-            /* inf -> Inf, nan -> Nan */
-            if (*buf == 'i' || *buf == 'n') {
-                *buf = toupper(UCHAR(*buf));
-            }
-            if (*buf == 'I') {
-                /* Infinity -> Inf */
-                buf[3] = '\0';
-                len = buf - buf0 + 3;
-            }
-            return len;
+    /* Can just do a regular base-10 conversion */
+    return strtol(str, endptr, 10);
+}
+
+
+/* Converts a number as per strtoull(..., 0) except leading zeros do *not*
+ * imply octal. Instead, decimal is assumed unless the number begins with 0x, 0o or 0b
+ */
+static jim_wide jim_strtoull(const char *str, char **endptr)
+{
+#ifdef HAVE_LONG_LONG
+    int sign;
+    int base;
+    int i = JimNumberBase(str, &base, &sign);
+
+    if (base != 10) {
+        jim_wide value = strtoull(str + i, endptr, base);
+        if (endptr == NULL || *endptr != str + i) {
+            return value * sign;
         }
-        buf++;
     }
 
-    *buf++ = '.';
-    *buf++ = '0';
-    *buf = '\0';
+    /* Can just do a regular base-10 conversion */
+    return strtoull(str, endptr, 10);
+#else
+    return (unsigned long)jim_strtol(str, endptr);
+#endif
+}
+
+int Jim_StringToWide(const char *str, jim_wide * widePtr, int base)
+{
+    char *endptr;
+
+    if (base) {
+        *widePtr = strtoull(str, &endptr, base);
+    }
+    else {
+        *widePtr = jim_strtoull(str, &endptr);
+    }
 
-    return len + 2;
+    return JimCheckConversion(str, endptr);
 }
 
 int Jim_StringToDouble(const char *str, double *doublePtr)
@@ -520,7 +577,7 @@ static jim_wide JimPowWide(jim_wide b, jim_wide e)
  * Special functions
  * ---------------------------------------------------------------------------*/
 #ifdef JIM_DEBUG_PANIC
-void JimPanicDump(int condition, const char *fmt, ...)
+static void JimPanicDump(int condition, const char *fmt, ...)
 {
     va_list ap;
 
@@ -530,9 +587,9 @@ void JimPanicDump(int condition, const char *fmt, ...)
 
     va_start(ap, fmt);
 
-    fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
+    fprintf(stderr, "\nJIM INTERPRETER PANIC: ");
     vfprintf(stderr, fmt, ap);
-    fprintf(stderr, JIM_NL JIM_NL);
+    fprintf(stderr, "\n\n");
     va_end(ap);
 
 #ifdef HAVE_BACKTRACE
@@ -544,13 +601,13 @@ void JimPanicDump(int condition, const char *fmt, ...)
         size = backtrace(array, 40);
         strings = backtrace_symbols(array, size);
         for (i = 0; i < size; i++)
-            fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]);
-        fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL);
-        fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
+            fprintf(stderr, "[backtrace] %s\n", strings[i]);
+        fprintf(stderr, "[backtrace] Include the above lines and the output\n");
+        fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report.\n");
     }
 #endif
 
-    abort();
+    exit(1);
 }
 #endif
 
@@ -560,7 +617,7 @@ void JimPanicDump(int condition, const char *fmt, ...)
 
 void *Jim_Alloc(int size)
 {
-    return malloc(size);
+    return size ? malloc(size) : NULL;
 }
 
 void Jim_Free(void *ptr)
@@ -591,7 +648,7 @@ char *Jim_StrDupLen(const char *s, int l)
  * Time related functions
  * ---------------------------------------------------------------------------*/
 
-/* Returns microseconds of CPU used since start. */
+/* Returns current time in microseconds */
 static jim_wide JimClock(void)
 {
     struct timeval tv;
@@ -605,9 +662,9 @@ static jim_wide JimClock(void)
  * ---------------------------------------------------------------------------*/
 
 /* -------------------------- private prototypes ---------------------------- */
-static int JimExpandHashTableIfNeeded(Jim_HashTable *ht);
+static void JimExpandHashTableIfNeeded(Jim_HashTable *ht);
 static unsigned int JimHashTableNextPower(unsigned int size);
-static int JimInsertHashEntry(Jim_HashTable *ht, const void *key);
+static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace);
 
 /* -------------------------- hash functions -------------------------------- */
 
@@ -636,8 +693,7 @@ unsigned int Jim_GenHashFunction(const unsigned char *buf, int len)
 
 /* ----------------------------- API implementation ------------------------- */
 
-/* reset a hashtable already initialized with ht_init().
- * NOTE: This function should only called by ht_destroy(). */
+/* reset a hashtable already initialized */
 static void JimResetHashTable(Jim_HashTable *ht)
 {
     ht->table = NULL;
@@ -645,6 +701,22 @@ static void JimResetHashTable(Jim_HashTable *ht)
     ht->sizemask = 0;
     ht->used = 0;
     ht->collisions = 0;
+#ifdef JIM_RANDOMISE_HASH
+    /* This is initialised to a random value to avoid a hash collision attack.
+     * See: n.runs-SA-2011.004
+     */
+    ht->uniq = (rand() ^ time(NULL) ^ clock());
+#else
+    ht->uniq = 0;
+#endif
+}
+
+static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
+{
+    iter->ht = ht;
+    iter->index = -1;
+    iter->entry = NULL;
+    iter->nextEntry = NULL;
 }
 
 /* Initialize the hash table */
@@ -658,30 +730,32 @@ int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *pr
 
 /* Resize the table to the minimal size that contains all the elements,
  * but with the invariant of a USER/BUCKETS ration near to <= 1 */
-int Jim_ResizeHashTable(Jim_HashTable *ht)
+void Jim_ResizeHashTable(Jim_HashTable *ht)
 {
     int minimal = ht->used;
 
     if (minimal < JIM_HT_INITIAL_SIZE)
         minimal = JIM_HT_INITIAL_SIZE;
-    return Jim_ExpandHashTable(ht, minimal);
+    Jim_ExpandHashTable(ht, minimal);
 }
 
 /* Expand or create the hashtable */
-int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
+void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
 {
     Jim_HashTable n;            /* the new hashtable */
     unsigned int realsize = JimHashTableNextPower(size), i;
 
     /* the size is invalid if it is smaller than the number of
      * elements already inside the hashtable */
-    if (ht->used >= size)
-        return JIM_ERR;
+     if (size <= ht->used)
+        return;
 
     Jim_InitHashTable(&n, ht->type, ht->privdata);
     n.size = realsize;
     n.sizemask = realsize - 1;
     n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *));
+    /* Keep the same 'uniq' as the original */
+    n.uniq = ht->uniq;
 
     /* Initialize all the pointers to NULL */
     memset(n.table, 0, realsize * sizeof(Jim_HashEntry *));
@@ -716,47 +790,59 @@ int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
 
     /* Remap the new hashtable in the old */
     *ht = n;
-    return JIM_OK;
 }
 
 /* Add an element to the target hash table */
 int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
 {
-    int idx;
     Jim_HashEntry *entry;
 
     /* Get the index of the new element, or -1 if
      * the element already exists. */
-    if ((idx = JimInsertHashEntry(ht, key)) == -1)
+    entry = JimInsertHashEntry(ht, key, 0);
+    if (entry == NULL)
         return JIM_ERR;
 
-    /* Allocates the memory and stores key */
-    entry = Jim_Alloc(sizeof(*entry));
-    entry->next = ht->table[idx];
-    ht->table[idx] = entry;
-
     /* Set the hash entry fields. */
     Jim_SetHashKey(ht, entry, key);
     Jim_SetHashVal(ht, entry, val);
-    ht->used++;
     return JIM_OK;
 }
 
 /* Add an element, discarding the old if the key already exists */
 int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val)
 {
+    int existed;
     Jim_HashEntry *entry;
 
-    /* Try to add the element. If the key
-     * does not exists Jim_AddHashEntry will suceed. */
-    if (Jim_AddHashEntry(ht, key, val) == JIM_OK)
-        return JIM_OK;
-    /* It already exists, get the entry */
-    entry = Jim_FindHashEntry(ht, key);
-    /* Free the old value and set the new one */
-    Jim_FreeEntryVal(ht, entry);
-    Jim_SetHashVal(ht, entry, val);
-    return JIM_OK;
+    /* Get the index of the new element, or -1 if
+     * the element already exists. */
+    entry = JimInsertHashEntry(ht, key, 1);
+    if (entry->key) {
+        /* It already exists, so only replace the value.
+         * Note if both a destructor and a duplicate function exist,
+         * need to dup before destroy. perhaps they are the same
+         * reference counted object
+         */
+        if (ht->type->valDestructor && ht->type->valDup) {
+            void *newval = ht->type->valDup(ht->privdata, val);
+            ht->type->valDestructor(ht->privdata, entry->u.val);
+            entry->u.val = newval;
+        }
+        else {
+            Jim_FreeEntryVal(ht, entry);
+            Jim_SetHashVal(ht, entry, val);
+        }
+        existed = 1;
+    }
+    else {
+        /* Doesn't exist, so set the key */
+        Jim_SetHashKey(ht, entry, key);
+        Jim_SetHashVal(ht, entry, val);
+        existed = 0;
+    }
+
+    return existed;
 }
 
 /* Search and remove an element */
@@ -790,7 +876,7 @@ int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
     return JIM_ERR;             /* not found */
 }
 
-/* Destroy an entire hash table */
+/* Destroy an entire hash table and leave it ready for reuse */
 int Jim_FreeHashTable(Jim_HashTable *ht)
 {
     unsigned int i;
@@ -837,11 +923,7 @@ Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
 Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
 {
     Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
-
-    iter->ht = ht;
-    iter->index = -1;
-    iter->entry = NULL;
-    iter->nextEntry = NULL;
+    JimInitHashTableIterator(ht, iter);
     return iter;
 }
 
@@ -870,15 +952,14 @@ Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
 /* ------------------------- private functions ------------------------------ */
 
 /* Expand the hash table if needed */
-static int JimExpandHashTableIfNeeded(Jim_HashTable *ht)
+static void JimExpandHashTableIfNeeded(Jim_HashTable *ht)
 {
     /* If the hash table is empty expand it to the intial size,
      * if the table is "full" dobule its size. */
     if (ht->size == 0)
-        return Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE);
+        Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE);
     if (ht->size == ht->used)
-        return Jim_ExpandHashTable(ht, ht->size * 2);
-    return JIM_OK;
+        Jim_ExpandHashTable(ht, ht->size * 2);
 }
 
 /* Our hash table capability is a power of two */
@@ -896,26 +977,34 @@ static unsigned int JimHashTableNextPower(unsigned int size)
 }
 
 /* Returns the index of a free slot that can be populated with
- * an hash entry for the given 'key'.
+ * a hash entry for the given 'key'.
  * If the key already exists, -1 is returned. */
-static int JimInsertHashEntry(Jim_HashTable *ht, const void *key)
+static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace)
 {
     unsigned int h;
     Jim_HashEntry *he;
 
     /* Expand the hashtable if needed */
-    if (JimExpandHashTableIfNeeded(ht) == JIM_ERR)
-        return -1;
+    JimExpandHashTableIfNeeded(ht);
+
     /* Compute the key hash value */
     h = Jim_HashKey(ht, key) & ht->sizemask;
     /* Search if this slot does not already contain the given key */
     he = ht->table[h];
     while (he) {
         if (Jim_CompareHashKeys(ht, key, he->key))
-            return -1;
+            return replace ? he : NULL;
         he = he->next;
     }
-    return h;
+
+    /* Allocates the memory and stores key */
+    he = Jim_Alloc(sizeof(*he));
+    he->next = ht->table[h];
+    ht->table[h] = he;
+    ht->used++;
+    he->key = NULL;
+
+    return he;
 }
 
 /* ----------------------- StringCopy Hash Table Type ------------------------*/
@@ -925,82 +1014,28 @@ static unsigned int JimStringCopyHTHashFunction(const void *key)
     return Jim_GenHashFunction(key, strlen(key));
 }
 
-static const void *JimStringCopyHTKeyDup(void *privdata, const void *key)
-{
-    int len = strlen(key);
-    char *copy = Jim_Alloc(len + 1);
-
-    JIM_NOTUSED(privdata);
-
-    memcpy(copy, key, len);
-    copy[len] = '\0';
-    return copy;
-}
-
-static void *JimStringKeyValCopyHTValDup(void *privdata, const void *val)
+static void *JimStringCopyHTDup(void *privdata, const void *key)
 {
-    int len = strlen(val);
-    char *copy = Jim_Alloc(len + 1);
-
-    JIM_NOTUSED(privdata);
-
-    memcpy(copy, val, len);
-    copy[len] = '\0';
-    return copy;
+    return Jim_StrDup(key);
 }
 
 static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2)
 {
-    JIM_NOTUSED(privdata);
-
     return strcmp(key1, key2) == 0;
 }
 
-static void JimStringCopyHTKeyDestructor(void *privdata, const void *key)
+static void JimStringCopyHTKeyDestructor(void *privdata, void *key)
 {
-    JIM_NOTUSED(privdata);
-
-    Jim_Free((void *)key);      /* ATTENTION: const cast */
-}
-
-static void JimStringKeyValCopyHTValDestructor(void *privdata, void *val)
-{
-    JIM_NOTUSED(privdata);
-
-    Jim_Free((void *)val);      /* ATTENTION: const cast */
+    Jim_Free(key);
 }
 
-#if 0
-static Jim_HashTableType JimStringCopyHashTableType = {
-    JimStringCopyHTHashFunction,        /* hash function */
-    JimStringCopyHTKeyDup,      /* key dup */
-    NULL,                       /* val dup */
-    JimStringCopyHTKeyCompare,  /* key compare */
-    JimStringCopyHTKeyDestructor,       /* key destructor */
-    NULL                        /* val destructor */
-};
-#endif
-
-/* This is like StringCopy but does not auto-duplicate the key.
- * It's used for intepreter's shared strings. */
-static const Jim_HashTableType JimSharedStringsHashTableType = {
-    JimStringCopyHTHashFunction,        /* hash function */
-    NULL,                       /* key dup */
-    NULL,                       /* val dup */
-    JimStringCopyHTKeyCompare,  /* key compare */
-    JimStringCopyHTKeyDestructor,       /* key destructor */
-    NULL                        /* val destructor */
-};
-
-/* This is like StringCopy but also automatically handle dynamic
- * allocated C strings as values. */
-static const Jim_HashTableType JimStringKeyValCopyHashTableType = {
-    JimStringCopyHTHashFunction,        /* hash function */
-    JimStringCopyHTKeyDup,      /* key dup */
-    JimStringKeyValCopyHTValDup,        /* val dup */
-    JimStringCopyHTKeyCompare,  /* key compare */
-    JimStringCopyHTKeyDestructor,       /* key destructor */
-    JimStringKeyValCopyHTValDestructor, /* val destructor */
+static const Jim_HashTableType JimPackageHashTableType = {
+    JimStringCopyHTHashFunction,     /* hash function */
+    JimStringCopyHTDup,              /* key dup */
+    NULL,                            /* val dup */
+    JimStringCopyHTKeyCompare,       /* key compare */
+    JimStringCopyHTKeyDestructor,    /* key destructor */
+    NULL                             /* val destructor */
 };
 
 typedef struct AssocDataValue
@@ -1019,11 +1054,11 @@ static void JimAssocDataHashTableValueDestructor(void *privdata, void *data)
 }
 
 static const Jim_HashTableType JimAssocDataHashTableType = {
-    JimStringCopyHTHashFunction,        /* hash function */
-    JimStringCopyHTKeyDup,      /* key dup */
-    NULL,                       /* val dup */
-    JimStringCopyHTKeyCompare,  /* key compare */
-    JimStringCopyHTKeyDestructor,       /* key destructor */
+    JimStringCopyHTHashFunction,    /* hash function */
+    JimStringCopyHTDup,             /* key dup */
+    NULL,                           /* val dup */
+    JimStringCopyHTKeyCompare,      /* key compare */
+    JimStringCopyHTKeyDestructor,   /* key destructor */
     JimAssocDataHashTableValueDestructor        /* val destructor */
 };
 
@@ -1084,18 +1119,18 @@ void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr))
 }
 
 /* -----------------------------------------------------------------------------
- * Parser
+ * Tcl Parser
  * ---------------------------------------------------------------------------*/
 
 /* Token types */
-#define JIM_TT_NONE    0           /* No token returned */
+#define JIM_TT_NONE    0          /* No token returned */
 #define JIM_TT_STR     1          /* simple string */
 #define JIM_TT_ESC     2          /* string that needs escape chars conversion */
 #define JIM_TT_VAR     3          /* var substitution */
 #define JIM_TT_DICTSUGAR   4      /* Syntax sugar for [dict get], $foo(bar) */
 #define JIM_TT_CMD     5          /* command substitution */
 /* Note: Keep these three together for TOKEN_IS_SEP() */
-#define JIM_TT_SEP     6          /* word separator. arg is # of tokens. -ve if {*} */
+#define JIM_TT_SEP     6          /* word separator (white space) */
 #define JIM_TT_EOL     7          /* line separator */
 #define JIM_TT_EOF     8          /* end of script */
 
@@ -1121,6 +1156,14 @@ void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr))
 #define JIM_PS_QUOTE 1          /* Inside "" */
 #define JIM_PS_DICTSUGAR 2      /* Tokenising abc(def) into 4 separate tokens */
 
+/**
+ * Results of missing quotes, braces, etc. from parsing.
+ */
+struct JimParseMissing {
+    int ch;             /* At end of parse, ' ' if complete, '{' if braces incomplete, '"' if quotes incomplete */
+    int line;           /* Line number starting the missing token */
+};
+
 /* Parser context structure. The same context is used both to parse
  * Tcl scripts and lists. */
 struct JimParserCtx
@@ -1135,16 +1178,7 @@ struct JimParserCtx
     int eof;                    /* Non zero if EOF condition is true. */
     int state;                  /* Parser state */
     int comment;                /* Non zero if the next chars may be a comment. */
-    char missing;               /* At end of parse, ' ' if complete, '{' if braces incomplete, '"' if quotes incomplete */
-    int missingline;            /* Line number starting the missing token */
-};
-
-/**
- * Results of missing quotes, braces, etc. from parsing.
- */
-struct JimParseResult {
-    char missing;               /* From JimParserCtx.missing */
-    int line;                   /* From JimParserCtx.missingline */
+    struct JimParseMissing missing;   /* Details of any missing quotes, etc. */
 };
 
 static int JimParseScript(struct JimParserCtx *pc);
@@ -1158,7 +1192,6 @@ static int JimParseStr(struct JimParserCtx *pc);
 static int JimParseComment(struct JimParserCtx *pc);
 static void JimParseSubCmd(struct JimParserCtx *pc);
 static int JimParseSubQuote(struct JimParserCtx *pc);
-static void JimParseSubCmd(struct JimParserCtx *pc);
 static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc);
 
 /* Initialize a parser context.
@@ -1176,8 +1209,8 @@ static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int
     pc->state = JIM_PS_DEF;
     pc->linenr = linenr;
     pc->comment = 1;
-    pc->missing = ' ';
-    pc->missingline = linenr;
+    pc->missing.ch = ' ';
+    pc->missing.line = linenr;
 }
 
 static int JimParseScript(struct JimParserCtx *pc)
@@ -1196,57 +1229,43 @@ static int JimParseScript(struct JimParserCtx *pc)
                 if (*(pc->p + 1) == '\n' && pc->state == JIM_PS_DEF) {
                     return JimParseSep(pc);
                 }
-                else {
-                    pc->comment = 0;
-                    return JimParseStr(pc);
-                }
-                break;
+                pc->comment = 0;
+                return JimParseStr(pc);
             case ' ':
             case '\t':
             case '\r':
+            case '\f':
                 if (pc->state == JIM_PS_DEF)
                     return JimParseSep(pc);
-                else {
-                    pc->comment = 0;
-                    return JimParseStr(pc);
-                }
-                break;
+                pc->comment = 0;
+                return JimParseStr(pc);
             case '\n':
             case ';':
                 pc->comment = 1;
                 if (pc->state == JIM_PS_DEF)
                     return JimParseEol(pc);
-                else
-                    return JimParseStr(pc);
-                break;
+                return JimParseStr(pc);
             case '[':
                 pc->comment = 0;
                 return JimParseCmd(pc);
-                break;
             case '$':
                 pc->comment = 0;
                 if (JimParseVar(pc) == JIM_ERR) {
+                    /* An orphan $. Create as a separate token */
                     pc->tstart = pc->tend = pc->p++;
                     pc->len--;
-                    pc->tline = pc->linenr;
-                    pc->tt = JIM_TT_STR;
-                    return JIM_OK;
+                    pc->tt = JIM_TT_ESC;
                 }
-                else
-                    return JIM_OK;
-                break;
+                return JIM_OK;
             case '#':
                 if (pc->comment) {
                     JimParseComment(pc);
                     continue;
                 }
-                else {
-                    return JimParseStr(pc);
-                }
+                return JimParseStr(pc);
             default:
                 pc->comment = 0;
                 return JimParseStr(pc);
-                break;
         }
         return JIM_OK;
     }
@@ -1256,8 +1275,10 @@ static int JimParseSep(struct JimParserCtx *pc)
 {
     pc->tstart = pc->p;
     pc->tline = pc->linenr;
-    while (*pc->p == ' ' || *pc->p == '\t' || *pc->p == '\r' ||
-        (*pc->p == '\\' && *(pc->p + 1) == '\n')) {
+    while (isspace(UCHAR(*pc->p)) || (*pc->p == '\\' && *(pc->p + 1) == '\n')) {
+        if (*pc->p == '\n') {
+            break;
+        }
         if (*pc->p == '\\') {
             pc->p++;
             pc->len--;
@@ -1275,7 +1296,7 @@ static int JimParseEol(struct JimParserCtx *pc)
 {
     pc->tstart = pc->p;
     pc->tline = pc->linenr;
-    while (*pc->p == ' ' || *pc->p == '\n' || *pc->p == '\t' || *pc->p == '\r' || *pc->p == ';') {
+    while (isspace(UCHAR(*pc->p)) || *pc->p == ';') {
         if (*pc->p == '\n')
             pc->linenr++;
         pc->p++;
@@ -1352,8 +1373,8 @@ static void JimParseSubBrace(struct JimParserCtx *pc)
         pc->p++;
         pc->len--;
     }
-    pc->missing = '{';
-    pc->missingline = pc->tline;
+    pc->missing.ch = '{';
+    pc->missing.line = pc->tline;
     pc->tend = pc->p - 1;
 }
 
@@ -1409,8 +1430,8 @@ static int JimParseSubQuote(struct JimParserCtx *pc)
         pc->p++;
         pc->len--;
     }
-    pc->missing = '"';
-    pc->missingline = line;
+    pc->missing.ch = '"';
+    pc->missing.line = line;
     pc->tend = pc->p - 1;
     return tt;
 }
@@ -1474,8 +1495,8 @@ static void JimParseSubCmd(struct JimParserCtx *pc)
         pc->p++;
         pc->len--;
     }
-    pc->missing = '[';
-    pc->missingline = line;
+    pc->missing.ch = '[';
+    pc->missing.line = line;
     pc->tend = pc->p - 1;
 }
 
@@ -1545,11 +1566,16 @@ static int JimParseVar(struct JimParserCtx *pc)
         while (1) {
             /* Skip double colon, but not single colon! */
             if (pc->p[0] == ':' && pc->p[1] == ':') {
-                pc->p += 2;
-                pc->len -= 2;
+                while (*pc->p == ':') {
+                    pc->p++;
+                    pc->len--;
+                }
                 continue;
             }
-            if (isalnum(UCHAR(*pc->p)) || *pc->p == '_') {
+            /* Note that any char >= 0x80 must be part of a utf-8 char.
+             * We consider all unicode points outside of ASCII as letters
+             */
+            if (isalnum(UCHAR(*pc->p)) || *pc->p == '_' || UCHAR(*pc->p) >= 0x80) {
                 pc->p++;
                 pc->len--;
                 continue;
@@ -1610,24 +1636,26 @@ static int JimParseVar(struct JimParserCtx *pc)
 
 static int JimParseStr(struct JimParserCtx *pc)
 {
-    int newword = (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
-        pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR);
-    if (newword && *pc->p == '{') {
-        return JimParseBrace(pc);
-    }
-    else if (newword && *pc->p == '"') {
-        pc->state = JIM_PS_QUOTE;
-        pc->p++;
-        pc->len--;
-        /* In case the end quote is missing */
-        pc->missingline = pc->tline;
+    if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
+        pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) {
+        /* Starting a new word */
+        if (*pc->p == '{') {
+            return JimParseBrace(pc);
+        }
+        if (*pc->p == '"') {
+            pc->state = JIM_PS_QUOTE;
+            pc->p++;
+            pc->len--;
+            /* In case the end quote is missing */
+            pc->missing.line = pc->tline;
+        }
     }
     pc->tstart = pc->p;
     pc->tline = pc->linenr;
     while (1) {
         if (pc->len == 0) {
             if (pc->state == JIM_PS_QUOTE) {
-                pc->missing = '"';
+                pc->missing.ch = '"';
             }
             pc->tend = pc->p - 1;
             pc->tt = JIM_TT_ESC;
@@ -1647,6 +1675,10 @@ static int JimParseStr(struct JimParserCtx *pc)
                     pc->p++;
                     pc->len--;
                 }
+                else if (pc->len == 1) {
+                    /* End of script with trailing backslash */
+                    pc->missing.ch = '\\';
+                }
                 break;
             case '(':
                 /* If the following token is not '$' just keep going */
@@ -1676,6 +1708,7 @@ static int JimParseStr(struct JimParserCtx *pc)
             case '\t':
             case '\n':
             case '\r':
+            case '\f':
             case ';':
                 if (pc->state == JIM_PS_DEF) {
                     pc->tend = pc->p - 1;
@@ -1706,13 +1739,22 @@ static int JimParseStr(struct JimParserCtx *pc)
 static int JimParseComment(struct JimParserCtx *pc)
 {
     while (*pc->p) {
-        if (*pc->p == '\n') {
-            pc->linenr++;
-            if (*(pc->p - 1) != '\\') {
-                pc->p++;
-                pc->len--;
+        if (*pc->p == '\\') {
+            pc->p++;
+            pc->len--;
+            if (pc->len == 0) {
+                pc->missing.ch = '\\';
                 return JIM_OK;
             }
+            if (*pc->p == '\n') {
+                pc->linenr++;
+            }
+        }
+        else if (*pc->p == '\n') {
+            pc->p++;
+            pc->len--;
+            pc->linenr++;
+            break;
         }
         pc->p++;
         pc->len--;
@@ -1783,32 +1825,61 @@ static int JimEscape(char *dest, const char *s, int slen)
                         i++;
                         break;
                     case 'u':
+                    case 'U':
                     case 'x':
                         /* A unicode or hex sequence.
-                         * \u Expect 1-4 hex chars and convert to utf-8.
                          * \x Expect 1-2 hex chars and convert to hex.
+                         * \u Expect 1-4 hex chars and convert to utf-8.
+                         * \U Expect 1-8 hex chars and convert to utf-8.
+                         * \u{NNN} supports 1-6 hex chars and convert to utf-8.
                          * An invalid sequence means simply the escaped char.
                          */
                         {
-                            int val = 0;
+                            unsigned val = 0;
                             int k;
+                            int maxchars = 2;
 
                             i++;
 
-                            for (k = 0; k < (s[i] == 'u' ? 4 : 2); k++) {
+                            if (s[i] == 'U') {
+                                maxchars = 8;
+                            }
+                            else if (s[i] == 'u') {
+                                if (s[i + 1] == '{') {
+                                    maxchars = 6;
+                                    i++;
+                                }
+                                else {
+                                    maxchars = 4;
+                                }
+                            }
+
+                            for (k = 0; k < maxchars; k++) {
                                 int c = xdigitval(s[i + k + 1]);
                                 if (c == -1) {
                                     break;
                                 }
                                 val = (val << 4) | c;
                             }
+                            /* The \u{nnn} syntax supports up to 21 bit codepoints. */
+                            if (s[i] == '{') {
+                                if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') {
+                                    /* Back up */
+                                    i--;
+                                    k = 0;
+                                }
+                                else {
+                                    /* Skip the closing brace */
+                                    k++;
+                                }
+                            }
                             if (k) {
                                 /* Got a valid sequence, so convert */
-                                if (s[i] == 'u') {
-                                    p += utf8_fromunicode(p, val);
+                                if (s[i] == 'x') {
+                                    *p++ = val;
                                 }
                                 else {
-                                    *p++ = val;
+                                    p += utf8_fromunicode(p, val);
                                 }
                                 i += k;
                                 break;
@@ -1938,6 +2009,7 @@ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc
  * '{' on scripts incomplete missing one or more '}' to be balanced.
  * '[' on scripts incomplete missing one or more ']' to be balanced.
  * '"' on scripts incomplete missing a '"' char.
+ * '\\' on scripts with a trailing backslash.
  *
  * If the script is complete, 1 is returned, otherwise 0.
  */
@@ -1950,9 +2022,9 @@ int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr)
         JimParseScript(&parser);
     }
     if (stateCharPtr) {
-        *stateCharPtr = parser.missing;
+        *stateCharPtr = parser.missing.ch;
     }
-    return parser.missing == ' ';
+    return parser.missing.ch == ' ';
 }
 
 /* -----------------------------------------------------------------------------
@@ -1964,13 +2036,10 @@ static int JimParseListQuote(struct JimParserCtx *pc);
 
 static int JimParseList(struct JimParserCtx *pc)
 {
+    if (isspace(UCHAR(*pc->p))) {
+        return JimParseListSep(pc);
+    }
     switch (*pc->p) {
-        case ' ':
-        case '\n':
-        case '\t':
-        case '\r':
-            return JimParseListSep(pc);
-
         case '"':
             return JimParseListQuote(pc);
 
@@ -1995,7 +2064,7 @@ static int JimParseListSep(struct JimParserCtx *pc)
 {
     pc->tstart = pc->p;
     pc->tline = pc->linenr;
-    while (*pc->p == ' ' || *pc->p == '\t' || *pc->p == '\r' || *pc->p == '\n') {
+    while (isspace(UCHAR(*pc->p))) {
         if (*pc->p == '\n') {
             pc->linenr++;
         }
@@ -2051,22 +2120,18 @@ static int JimParseListStr(struct JimParserCtx *pc)
     pc->tt = JIM_TT_STR;
 
     while (pc->len) {
-        switch (*pc->p) {
-            case '\\':
-                if (--pc->len == 0) {
-                    /* Trailing backslash */
-                    pc->tend = pc->p;
-                    return JIM_OK;
-                }
-                pc->tt = JIM_TT_ESC;
-                pc->p++;
-                break;
-            case ' ':
-            case '\t':
-            case '\n':
-            case '\r':
-                pc->tend = pc->p - 1;
-                return JIM_OK;
+        if (isspace(UCHAR(*pc->p))) {
+            pc->tend = pc->p - 1;
+            return JIM_OK;
+        }
+        if (*pc->p == '\\') {
+            if (--pc->len == 0) {
+                /* Trailing backslash */
+                pc->tend = pc->p;
+                return JIM_OK;
+            }
+            pc->tt = JIM_TT_ESC;
+            pc->p++;
         }
         pc->p++;
         pc->len--;
@@ -2136,6 +2201,9 @@ void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
         objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
     if (interp->liveList == objPtr)
         interp->liveList = objPtr->nextObjPtr;
+#ifdef JIM_DISABLE_OBJECT_POOL
+    Jim_Free(objPtr);
+#else
     /* Link the object into the free objects list */
     objPtr->prevObjPtr = NULL;
     objPtr->nextObjPtr = interp->freeList;
@@ -2143,6 +2211,7 @@ void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
         interp->freeList->prevObjPtr = objPtr;
     interp->freeList = objPtr;
     objPtr->refCount = -1;
+#endif
 }
 
 /* Invalidate the string representation of an object. */
@@ -2155,25 +2224,6 @@ void Jim_InvalidateStringRep(Jim_Obj *objPtr)
     objPtr->bytes = NULL;
 }
 
-#define Jim_SetStringRep(o, b, l) \
-    do { (o)->bytes = b; (o)->length = l; } while (0)
-
-/* Set the initial string representation for an object.
- * Does not try to free an old one. */
-void Jim_InitStringRep(Jim_Obj *objPtr, const char *bytes, int length)
-{
-    if (length == 0) {
-        objPtr->bytes = JimEmptyStringRep;
-        objPtr->length = 0;
-    }
-    else {
-        objPtr->bytes = Jim_Alloc(length + 1);
-        objPtr->length = length;
-        memcpy(objPtr->bytes, bytes, length);
-        objPtr->bytes[length] = '\0';
-    }
-}
-
 /* Duplicate an object. The returned object has refcount = 0. */
 Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr)
 {
@@ -2184,8 +2234,18 @@ Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr)
         /* Object does not have a valid string representation. */
         dupPtr->bytes = NULL;
     }
+    else if (objPtr->length == 0) {
+        /* Zero length, so don't even bother with the type-specific dup, since all zero length objects look the same */
+        dupPtr->bytes = JimEmptyStringRep;
+        dupPtr->length = 0;
+        dupPtr->typePtr = NULL;
+        return dupPtr;
+    }
     else {
-        Jim_InitStringRep(dupPtr, objPtr->bytes, objPtr->length);
+        dupPtr->bytes = Jim_Alloc(objPtr->length + 1);
+        dupPtr->length = objPtr->length;
+        /* Copy the null byte too */
+        memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1);
     }
 
     /* By default, the new object has the same type as the old object */
@@ -2202,9 +2262,10 @@ Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr)
     return dupPtr;
 }
 
-/* Return the string representation for objPtr. If the object
- * string representation is invalid, calls the method to create
- * a new one starting from the internal representation of the object. */
+/* Return the string representation for objPtr. If the object's
+ * string representation is invalid, calls the updateStringProc method to create
+ * a new one from the internal representation of the object.
+ */
 const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
 {
     if (objPtr->bytes == NULL) {
@@ -2220,10 +2281,29 @@ const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
 /* Just returns the length of the object's string rep */
 int Jim_Length(Jim_Obj *objPtr)
 {
-    int len;
+    if (objPtr->bytes == NULL) {
+        /* Invalid string repr. Generate it. */
+        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+        objPtr->typePtr->updateStringProc(objPtr);
+    }
+    return objPtr->length;
+}
 
-    Jim_GetString(objPtr, &len);
-    return len;
+/* Just returns the length of the object's string rep */
+const char *Jim_String(Jim_Obj *objPtr)
+{
+    if (objPtr->bytes == NULL) {
+        /* Invalid string repr. Generate it. */
+        JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+        objPtr->typePtr->updateStringProc(objPtr);
+    }
+    return objPtr->bytes;
+}
+
+static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
+{
+    objPtr->bytes = Jim_StrDup(str);
+    objPtr->length = strlen(str);
 }
 
 static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -2239,7 +2319,7 @@ static const Jim_ObjType dictSubstObjType = {
 
 static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
 {
-    Jim_DecrRefCount(interp, (Jim_Obj *)objPtr->internalRep.twoPtrValue.ptr2);
+    Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr);
 }
 
 static const Jim_ObjType interpolatedObjType = {
@@ -2271,24 +2351,29 @@ static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *d
     /* This is a bit subtle: the only caller of this function
      * should be Jim_DuplicateObj(), that will copy the
      * string representaion. After the copy, the duplicated
-     * object will not have more room in teh buffer than
+     * object will not have more room in the buffer than
      * srcPtr->length bytes. So we just set it to length. */
     dupPtr->internalRep.strValue.maxLength = srcPtr->length;
-
     dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength;
 }
 
 static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 {
-    /* Get a fresh string representation. */
-    (void)Jim_String(objPtr);
-    /* Free any other internal representation. */
-    Jim_FreeIntRep(interp, objPtr);
-    /* Set it as string, i.e. just set the maxLength field. */
-    objPtr->typePtr = &stringObjType;
-    objPtr->internalRep.strValue.maxLength = objPtr->length;
-    /* Don't know the utf-8 length yet */
-    objPtr->internalRep.strValue.charLength = -1;
+    if (objPtr->typePtr != &stringObjType) {
+        /* Get a fresh string representation. */
+        if (objPtr->bytes == NULL) {
+            /* Invalid string repr. Generate it. */
+            JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name));
+            objPtr->typePtr->updateStringProc(objPtr);
+        }
+        /* Free any other internal representation. */
+        Jim_FreeIntRep(interp, objPtr);
+        /* Set it as string, i.e. just set the maxLength field. */
+        objPtr->typePtr = &stringObjType;
+        objPtr->internalRep.strValue.maxLength = objPtr->length;
+        /* Don't know the utf-8 length yet */
+        objPtr->internalRep.strValue.charLength = -1;
+    }
     return JIM_OK;
 }
 
@@ -2300,8 +2385,7 @@ static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr)
 {
 #ifdef JIM_UTF8
-    if (objPtr->typePtr != &stringObjType)
-        SetStringFromAny(interp, objPtr);
+    SetStringFromAny(interp, objPtr);
 
     if (objPtr->internalRep.strValue.charLength < 0) {
         objPtr->internalRep.strValue.charLength = utf8_strlen(objPtr->bytes, objPtr->length);
@@ -2323,14 +2407,13 @@ Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
     /* Alloc/Set the string rep. */
     if (len == 0) {
         objPtr->bytes = JimEmptyStringRep;
-        objPtr->length = 0;
     }
     else {
         objPtr->bytes = Jim_Alloc(len + 1);
-        objPtr->length = len;
         memcpy(objPtr->bytes, s, len);
         objPtr->bytes[len] = '\0';
     }
+    objPtr->length = len;
 
     /* No typePtr field for the vanilla string object. */
     objPtr->typePtr = NULL;
@@ -2363,14 +2446,13 @@ Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
 {
     Jim_Obj *objPtr = Jim_NewObj(interp);
 
-    if (len == -1)
-        len = strlen(s);
-    Jim_SetStringRep(objPtr, s, len);
+    objPtr->bytes = s;
+    objPtr->length = (len == -1) ? strlen(s) : len;
     objPtr->typePtr = NULL;
     return objPtr;
 }
 
-/* Low-level string append. Use it only against objects
+/* Low-level string append. Use it only against unshared objects
  * of type "string". */
 static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
 {
@@ -2396,6 +2478,7 @@ static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
     }
     memcpy(objPtr->bytes + objPtr->length, str, len);
     objPtr->bytes[objPtr->length + len] = '\0';
+
     if (objPtr->internalRep.strValue.charLength >= 0) {
         /* Update the utf-8 char length */
         objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len);
@@ -2403,21 +2486,20 @@ static void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
     objPtr->length += len;
 }
 
-/* Higher level API to append strings to objects. */
+/* Higher level API to append strings to objects.
+ * Object must not be unshared for each of these.
+ */
 void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len)
 {
     JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object"));
-    if (objPtr->typePtr != &stringObjType)
-        SetStringFromAny(interp, objPtr);
+    SetStringFromAny(interp, objPtr);
     StringAppendString(objPtr, str, len);
 }
 
 void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
 {
     int len;
-    const char *str;
-
-    str = Jim_GetString(appendObjPtr, &len);
+    const char *str = Jim_GetString(appendObjPtr, &len);
     Jim_AppendString(interp, objPtr, str, len);
 }
 
@@ -2425,11 +2507,10 @@ void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
 {
     va_list ap;
 
-    if (objPtr->typePtr != &stringObjType)
-        SetStringFromAny(interp, objPtr);
+    SetStringFromAny(interp, objPtr);
     va_start(ap, objPtr);
     while (1) {
-        char *s = va_arg(ap, char *);
+        const char *s = va_arg(ap, const char *);
 
         if (s == NULL)
             break;
@@ -2440,41 +2521,59 @@ void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
 
 int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr)
 {
-    const char *aStr, *bStr;
-    int aLen, bLen;
-
-    if (aObjPtr == bObjPtr)
+    if (aObjPtr == bObjPtr) {
         return 1;
-    aStr = Jim_GetString(aObjPtr, &aLen);
-    bStr = Jim_GetString(bObjPtr, &bLen);
-    if (aLen != bLen)
-        return 0;
-    return JimStringCompare(aStr, aLen, bStr, bLen) == 0;
+    }
+    else {
+        int Alen, Blen;
+        const char *sA = Jim_GetString(aObjPtr, &Alen);
+        const char *sB = Jim_GetString(bObjPtr, &Blen);
+
+        return Alen == Blen && memcmp(sA, sB, Alen) == 0;
+    }
 }
 
+/**
+ * Note. Does not support embedded nulls in either the pattern or the object.
+ */
 int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase)
 {
-    return JimStringMatch(interp, patternObjPtr, Jim_String(objPtr), nocase);
+    return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase);
 }
 
+/*
+ * Note: does not support embedded nulls for the nocase option.
+ */
 int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase)
 {
-    const char *s1, *s2;
     int l1, l2;
-
-    s1 = Jim_GetString(firstObjPtr, &l1);
-    s2 = Jim_GetString(secondObjPtr, &l2);
+    const char *s1 = Jim_GetString(firstObjPtr, &l1);
+    const char *s2 = Jim_GetString(secondObjPtr, &l2);
 
     if (nocase) {
-        return JimStringCompareNoCase(s1, s2, -1);
+        /* Do a character compare for nocase */
+        return JimStringCompareLen(s1, s2, -1, nocase);
     }
     return JimStringCompare(s1, l1, s2, l2);
 }
 
+/**
+ * Like Jim_StringCompareObj() except compares to a maximum of the length of firstObjPtr.
+ *
+ * Note: does not support embedded nulls
+ */
+int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase)
+{
+    const char *s1 = Jim_String(firstObjPtr);
+    const char *s2 = Jim_String(secondObjPtr);
+
+    return JimStringCompareLen(s1, s2, Jim_Utf8Length(interp, firstObjPtr), nocase);
+}
+
 /* Convert a range, as returned by Jim_GetRange(), into
  * an absolute index into an object of the specified length.
  * This function may return negative values, or values
- * bigger or equal to the length of the list if the index
+ * greater than or equal to the length of the list if the index
  * is out of range. */
 static int JimRelToAbsIndex(int len, int idx)
 {
@@ -2483,41 +2582,53 @@ static int JimRelToAbsIndex(int len, int idx)
     return idx;
 }
 
-/* Convert a pair of index as normalize by JimRelToAbsIndex(),
- * into a range stored in *firstPtr, *lastPtr, *rangeLenPtr, suitable
- * for implementation of commands like [string range] and [lrange].
+/* Convert a pair of indexes (*firstPtr, *lastPtr) as normalized by JimRelToAbsIndex(),
+ * into a form suitable for implementation of commands like [string range] and [lrange].
  *
  * The resulting range is guaranteed to address valid elements of
- * the structure. */
-static void JimRelToAbsRange(int len, int first, int last,
-    int *firstPtr, int *lastPtr, int *rangeLenPtr)
+ * the structure.
+ */
+static void JimRelToAbsRange(int len, int *firstPtr, int *lastPtr, int *rangeLenPtr)
 {
     int rangeLen;
 
-    if (first > last) {
+    if (*firstPtr > *lastPtr) {
         rangeLen = 0;
     }
     else {
-        rangeLen = last - first + 1;
+        rangeLen = *lastPtr - *firstPtr + 1;
         if (rangeLen) {
-            if (first < 0) {
-                rangeLen += first;
-                first = 0;
+            if (*firstPtr < 0) {
+                rangeLen += *firstPtr;
+                *firstPtr = 0;
             }
-            if (last >= len) {
-                rangeLen -= (last - (len - 1));
-                last = len - 1;
+            if (*lastPtr >= len) {
+                rangeLen -= (*lastPtr - (len - 1));
+                *lastPtr = len - 1;
             }
         }
     }
     if (rangeLen < 0)
         rangeLen = 0;
 
-    *firstPtr = first;
-    *lastPtr = last;
     *rangeLenPtr = rangeLen;
 }
 
+static int JimStringGetRange(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr,
+    int len, int *first, int *last, int *range)
+{
+    if (Jim_GetIndex(interp, firstObjPtr, first) != JIM_OK) {
+        return JIM_ERR;
+    }
+    if (Jim_GetIndex(interp, lastObjPtr, last) != JIM_OK) {
+        return JIM_ERR;
+    }
+    *first = JimRelToAbsIndex(len, *first);
+    *last = JimRelToAbsIndex(len, *last);
+    JimRelToAbsRange(len, first, last, range);
+    return JIM_OK;
+}
+
 Jim_Obj *Jim_StringByteRangeObj(Jim_Interp *interp,
     Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr)
 {
@@ -2526,13 +2637,12 @@ Jim_Obj *Jim_StringByteRangeObj(Jim_Interp *interp,
     int rangeLen;
     int bytelen;
 
-    if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
-        Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
-        return NULL;
     str = Jim_GetString(strObjPtr, &bytelen);
-    first = JimRelToAbsIndex(bytelen, first);
-    last = JimRelToAbsIndex(bytelen, last);
-    JimRelToAbsRange(bytelen, first, last, &first, &last, &rangeLen);
+
+    if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, bytelen, &first, &last, &rangeLen) != JIM_OK) {
+        return NULL;
+    }
+
     if (first == 0 && rangeLen == bytelen) {
         return strObjPtr;
     }
@@ -2548,14 +2658,13 @@ Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp,
     int len, rangeLen;
     int bytelen;
 
-    if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
-        Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
-        return NULL;
     str = Jim_GetString(strObjPtr, &bytelen);
     len = Jim_Utf8Length(interp, strObjPtr);
-    first = JimRelToAbsIndex(len, first);
-    last = JimRelToAbsIndex(len, last);
-    JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
+
+    if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) {
+        return NULL;
+    }
+
     if (first == 0 && rangeLen == len) {
         return strObjPtr;
     }
@@ -2569,48 +2678,131 @@ Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp,
 #endif
 }
 
-static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
+Jim_Obj *JimStringReplaceObj(Jim_Interp *interp,
+    Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr, Jim_Obj *newStrObj)
 {
-    char *buf, *p;
-    int len;
+    int first, last;
     const char *str;
+    int len, rangeLen;
+    Jim_Obj *objPtr;
 
-    if (strObjPtr->typePtr != &stringObjType) {
-        SetStringFromAny(interp, strObjPtr);
+    len = Jim_Utf8Length(interp, strObjPtr);
+
+    if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) {
+        return NULL;
     }
 
-    str = Jim_GetString(strObjPtr, &len);
+    if (last < first) {
+        return strObjPtr;
+    }
 
-    buf = p = Jim_Alloc(len + 1);
+    str = Jim_String(strObjPtr);
+
+    /* Before part */
+    objPtr = Jim_NewStringObjUtf8(interp, str, first);
+
+    /* Replacement */
+    if (newStrObj) {
+        Jim_AppendObj(interp, objPtr, newStrObj);
+    }
+
+    /* After part */
+    Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1);
+
+    return objPtr;
+}
+
+/**
+ * Note: does not support embedded nulls.
+ */
+static void JimStrCopyUpperLower(char *dest, const char *str, int uc)
+{
     while (*str) {
         int c;
         str += utf8_tounicode(str, &c);
-        p += utf8_fromunicode(p, utf8_lower(c));
+        dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c));
     }
-    *p = 0;
-    return Jim_NewStringObjNoAlloc(interp, buf, len);
+    *dest = 0;
 }
 
-static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
+/**
+ * Note: does not support embedded nulls.
+ */
+static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
 {
-    char *buf, *p;
+    char *buf;
     int len;
     const char *str;
 
+    SetStringFromAny(interp, strObjPtr);
+
+    str = Jim_GetString(strObjPtr, &len);
+
+#ifdef JIM_UTF8
+    /* Case mapping can change the utf-8 length of the string.
+     * But at worst it will be by one extra byte per char
+     */
+    len *= 2;
+#endif
+    buf = Jim_Alloc(len + 1);
+    JimStrCopyUpperLower(buf, str, 0);
+    return Jim_NewStringObjNoAlloc(interp, buf, -1);
+}
+
+/**
+ * Note: does not support embedded nulls.
+ */
+static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
+{
+    char *buf;
+    const char *str;
+    int len;
+
     if (strObjPtr->typePtr != &stringObjType) {
         SetStringFromAny(interp, strObjPtr);
     }
 
     str = Jim_GetString(strObjPtr, &len);
 
-    buf = p = Jim_Alloc(len + 1);
-    while (*str) {
-        int c;
-        str += utf8_tounicode(str, &c);
-        p += utf8_fromunicode(p, utf8_upper(c));
+#ifdef JIM_UTF8
+    /* Case mapping can change the utf-8 length of the string.
+     * But at worst it will be by one extra byte per char
+     */
+    len *= 2;
+#endif
+    buf = Jim_Alloc(len + 1);
+    JimStrCopyUpperLower(buf, str, 1);
+    return Jim_NewStringObjNoAlloc(interp, buf, -1);
+}
+
+/**
+ * Note: does not support embedded nulls.
+ */
+static Jim_Obj *JimStringToTitle(Jim_Interp *interp, Jim_Obj *strObjPtr)
+{
+    char *buf, *p;
+    int len;
+    int c;
+    const char *str;
+
+    str = Jim_GetString(strObjPtr, &len);
+    if (len == 0) {
+        return strObjPtr;
     }
-    *p = 0;
-    return Jim_NewStringObjNoAlloc(interp, buf, len);
+#ifdef JIM_UTF8
+    /* Case mapping can change the utf-8 length of the string.
+     * But at worst it will be by one extra byte per char
+     */
+    len *= 2;
+#endif
+    buf = p = Jim_Alloc(len + 1);
+
+    str += utf8_tounicode(str, &c);
+    p += utf8_getchars(p, utf8_title(c));
+
+    JimStrCopyUpperLower(p, str, 0);
+
+    return Jim_NewStringObjNoAlloc(interp, buf, -1);
 }
 
 /* Similar to memchr() except searches a UTF-8 string 'str' of byte length 'len'
@@ -2721,9 +2913,8 @@ static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_O
         trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen);
     }
 
-    if (strObjPtr->typePtr != &stringObjType) {
-        SetStringFromAny(interp, strObjPtr);
-    }
+    SetStringFromAny(interp, strObjPtr);
+
     len = Jim_Length(strObjPtr);
     nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen);
 
@@ -2732,6 +2923,7 @@ static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_O
         return Jim_NewEmptyStringObj(interp);
     }
     if (nontrim == strObjPtr->bytes + len) {
+        /* All non-trim, so return the original object */
         return strObjPtr;
     }
 
@@ -2755,15 +2947,24 @@ static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *t
     /* Now trim right */
     strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr);
 
-    if (objPtr != strObjPtr) {
-        /* Note that we don't want this object to be leaked */
-        Jim_IncrRefCount(objPtr);
-        Jim_DecrRefCount(interp, objPtr);
+    /* Note: refCount check is needed since objPtr may be emptyObj */
+    if (objPtr != strObjPtr && objPtr->refCount == 0) {
+        /* We don't want this object to be leaked */
+        Jim_FreeNewObj(interp, objPtr);
     }
 
     return strObjPtr;
 }
 
+/* Some platforms don't have isascii - need a non-macro version */
+#ifdef HAVE_ISASCII
+#define jim_isascii isascii
+#else
+static int jim_isascii(int c)
+{
+    return !(c & ~0x7f);
+}
+#endif
 
 static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict)
 {
@@ -2790,7 +2991,7 @@ static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass
 
     str = Jim_GetString(strObjPtr, &len);
     if (len == 0) {
-        Jim_SetResultInt(interp, !strict);
+        Jim_SetResultBool(interp, !strict);
         return JIM_OK;
     }
 
@@ -2798,20 +2999,20 @@ static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass
         case STR_IS_INTEGER:
             {
                 jim_wide w;
-                Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
+                Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK);
                 return JIM_OK;
             }
 
         case STR_IS_DOUBLE:
             {
                 double d;
-                Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
+                Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE);
                 return JIM_OK;
             }
 
         case STR_IS_ALPHA: isclassfunc = isalpha; break;
         case STR_IS_ALNUM: isclassfunc = isalnum; break;
-        case STR_IS_ASCII: isclassfunc = isascii; break;
+        case STR_IS_ASCII: isclassfunc = jim_isascii; break;
         case STR_IS_DIGIT: isclassfunc = isdigit; break;
         case STR_IS_LOWER: isclassfunc = islower; break;
         case STR_IS_UPPER: isclassfunc = isupper; break;
@@ -2827,11 +3028,11 @@ static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass
 
     for (i = 0; i < len; i++) {
         if (!isclassfunc(str[i])) {
-            Jim_SetResultInt(interp, 0);
+            Jim_SetResultBool(interp, 0);
             return JIM_OK;
         }
     }
-    Jim_SetResultInt(interp, 1);
+    Jim_SetResultBool(interp, 1);
     return JIM_OK;
 }
 
@@ -2839,13 +3040,13 @@ static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass
  * Compared String Object
  * ---------------------------------------------------------------------------*/
 
-/* This is strange object that allows to compare a C literal string
- * with a Jim object in very short time if the same comparison is done
+/* This is strange object that allows comparison of a C literal string
+ * with a Jim object in very short time if the same comparison is done
  * multiple times. For example every time the [if] command is executed,
- * Jim has to check if a given argument is "else". This comparions if
- * the code has no errors are true most of the times, so we can cache
- * inside the object the pointer of the string of the last matching
- * comparison. Because most C compilers perform literal sharing,
+ * Jim has to check if a given argument is "else".
+ * If the code has no errors, this comparison is true most of the time,
+ * so we can cache the pointer of the string of the last matching
+ * comparison inside the object. Because most C compilers perform literal sharing,
  * so that: char *x = "foo", char *y = "foo", will lead to x == y,
  * this works pretty well even if comparisons are at different places
  * inside the C code. */
@@ -2865,13 +3066,15 @@ static const Jim_ObjType comparedStringObjType = {
  * Note: this isn't binary safe, but it hardly needs to be.*/
 int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str)
 {
-    if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str)
+    if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) {
         return 1;
+    }
     else {
         const char *objStr = Jim_String(objPtr);
 
         if (strcmp(str, objStr) != 0)
             return 0;
+
         if (objPtr->typePtr != &comparedStringObjType) {
             Jim_FreeIntRep(interp, objPtr);
             objPtr->typePtr = &comparedStringObjType;
@@ -2894,22 +3097,20 @@ static int qsortCompareStringPointers(const void *a, const void *b)
  * Source Object
  *
  * This object is just a string from the language point of view, but
- * in the internal representation it contains the filename and line number
- * where this given token was read. This information is used by
+ * the internal representation contains the filename and line number
+ * where this token was read. This information is used by
  * Jim_EvalObj() if the object passed happens to be of type "source".
  *
- * This allows to propagate the information about line numbers and file
- * names and give error messages with absolute line numbers.
+ * This allows propagation of the information about line numbers and file
+ * names and gives error messages with absolute line numbers.
  *
- * Note that this object uses shared strings for filenames, and the
- * pointer to the filename together with the line number is taken into
- * the space for the "inline" internal representation of the Jim_Object,
- * so there is almost memory zero-overhead.
+ * Note that this object uses the internal representation of the Jim_Object,
+ * so there is almost no memory overhead. (One Jim_Obj for each filename).
  *
  * Also the object will be converted to something else if the given
  * token it represents in the source file is not something to be
  * evaluated (not a script), and will be specialized in some other way,
- * so the time overhead is also null.
+ * so the time overhead is also almost zero.
  * ---------------------------------------------------------------------------*/
 
 static void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
@@ -2930,7 +3131,7 @@ void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
 
 void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
 {
-    dupPtr->internalRep = srcPtr->internalRep;
+    dupPtr->internalRep.sourceValue = srcPtr->internalRep.sourceValue;
     Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj);
 }
 
@@ -2938,7 +3139,7 @@ static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
     Jim_Obj *fileNameObj, int lineNumber)
 {
     JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
-    JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typePtr != NULL"));
+    JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object"));
     Jim_IncrRefCount(fileNameObj);
     objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
     objPtr->internalRep.sourceValue.lineNumber = lineNumber;
@@ -2946,15 +3147,18 @@ static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
 }
 
 /* -----------------------------------------------------------------------------
- * Script Object
- * ---------------------------------------------------------------------------*/
-
+ * ScriptLine Object
+ *
+ * This object is used only in the Script internal represenation.
+ * For each line of the script, it holds the number of tokens on the line
+ * and the source line number.
+ */
 static const Jim_ObjType scriptLineObjType = {
     "scriptline",
     NULL,
     NULL,
     NULL,
-    0,
+    JIM_NONE,
 };
 
 static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
@@ -2975,11 +3179,16 @@ static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
     return objPtr;
 }
 
-#define JIM_CMDSTRUCT_EXPAND -1
-
+/* -----------------------------------------------------------------------------
+ * Script Object
+ *
+ * This object holds the parsed internal representation of a script.
+ * This representation is help within an allocated ScriptObj (see below)
+ */
 static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
 static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result);
+static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+static int JimParseCheckMissing(Jim_Interp *interp, int ch);
 
 static const Jim_ObjType scriptObjType = {
     "script",
@@ -2989,13 +3198,14 @@ static const Jim_ObjType scriptObjType = {
     JIM_TYPE_REFERENCES,
 };
 
-/* The ScriptToken structure represents every token into a scriptObj.
- * Every token contains an associated Jim_Obj that can be specialized
- * by commands operating on it. */
+/* Each token of a script is represented by a ScriptToken.
+ * The ScriptToken contains a type and a Jim_Obj. The Jim_Obj
+ * can be specialized by commands operating on it.
+ */
 typedef struct ScriptToken
 {
-    int type;
     Jim_Obj *objPtr;
+    int type;
 } ScriptToken;
 
 /* This is the script object internal representation. An array of
@@ -3007,7 +3217,7 @@ typedef struct ScriptToken
  * puts hello
  * set $i $x$y [foo]BAR
  *
- * will produce a ScriptObj with the following Tokens:
+ * will produce a ScriptObj with the following ScriptToken's:
  *
  * LIN 2
  * ESC puts
@@ -3057,26 +3267,27 @@ typedef struct ScriptToken
  * and "subst" objects. In the second case, the there are no LIN and WRD
  * tokens. Instead SEP and EOL tokens are added as-is.
  * In addition, the field 'substFlags' is used to represent the flags used to turn
- * the string into the internal representation used to perform the
- * substitution. If this flags are not what the application requires
+ * the string into the internal representation.
+ * If these flags do not match what the application requires,
  * the scriptObj is created again. For example the script:
  *
  * subst -nocommands $string
  * subst -novariables $string
  *
- * Will recreate the internal representation of the $string object
+ * Will (re)create the internal representation of the $string object
  * two times.
  */
 typedef struct ScriptObj
 {
-    int len;                    /* Length as number of tokens. */
     ScriptToken *token;         /* Tokens array. */
+    Jim_Obj *fileNameObj;       /* Filename */
+    int len;                    /* Length of token[] */
     int substFlags;             /* flags used for the compilation of "subst" objects */
     int inUse;                  /* Used to share a ScriptObj. Currently
                                    only used by Jim_EvalObj() as protection against
                                    shimmering of the currently evaluated object. */
-    Jim_Obj *fileNameObj;
-    int line;                   /* Line number of the first line */
+    int firstline;              /* Line number of the first line */
+    int linenr;                 /* Line number of the current line */
 } ScriptObj;
 
 void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
@@ -3084,8 +3295,7 @@ void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
     int i;
     struct ScriptObj *script = (void *)objPtr->internalRep.ptr;
 
-    script->inUse--;
-    if (script->inUse != 0)
+    if (--script->inUse != 0)
         return;
     for (i = 0; i < script->len; i++) {
         Jim_DecrRefCount(interp, script->token[i].objPtr);
@@ -3100,12 +3310,14 @@ void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
     JIM_NOTUSED(interp);
     JIM_NOTUSED(srcPtr);
 
-    /* Just returns an simple string. */
+    /* Just return a simple string. We don't try to preserve the source info
+     * since in practice scripts are never duplicated
+     */
     dupPtr->typePtr = NULL;
 }
 
-/* A simple parser token.
- * All the simple tokens for the script point into the same script string rep.
+/* A simple parse token.
+ * As the script is parsed, the created tokens point into the script string rep.
  */
 typedef struct
 {
@@ -3173,7 +3385,7 @@ static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len
     t->line = line;
 }
 
-/* Counts the number of adjoining non-separator.
+/* Counts the number of adjoining non-separator tokens.
  *
  * Returns -ve if the first token is the expansion
  * operator (in which case the count doesn't include
@@ -3210,15 +3422,15 @@ static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t)
     Jim_Obj *objPtr;
 
     if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) {
-        /* Convert the backlash escapes . */
+        /* Convert backlash escapes. The result will never be longer than the original */
         int len = t->len;
         char *str = Jim_Alloc(len + 1);
         len = JimEscape(str, t->token, len);
         objPtr = Jim_NewStringObjNoAlloc(interp, str, len);
     }
     else {
-        /* REVIST: Strictly, JIM_TT_STR should replace <backslash><newline><whitespace>
-         *         with a single space. This is currently not done.
+        /* XXX: For strict Tcl compatibility, JIM_TT_STR should replace <backslash><newline><whitespace>
+         *         with a single space.
          */
         objPtr = Jim_NewStringObj(interp, t->token, t->len);
     }
@@ -3261,7 +3473,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
             count++;
         }
     }
-    linenr = script->line = tokenlist->list[0].line;
+    linenr = script->firstline = tokenlist->list[0].line;
 
     token = script->token = Jim_Alloc(sizeof(ScriptToken) * count);
 
@@ -3294,7 +3506,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
             continue;
         }
         else if (wordtokens != 1) {
-            /* More than 1, or {expand}, so insert a WORD token */
+            /* More than 1, or {*}, so insert a WORD token */
             token->type = JIM_TT_WORD;
             token->objPtr = Jim_NewIntObj(interp, wordtokens);
             Jim_IncrRefCount(token->objPtr);
@@ -3321,7 +3533,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
             token->objPtr = JimMakeScriptObj(interp, t);
             Jim_IncrRefCount(token->objPtr);
 
-            /* Every object is initially a string, but the
+            /* Every object is initially a string of type 'source', but the
              * internal type may be specialized during execution of the
              * script. */
             JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line);
@@ -3335,7 +3547,7 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
 
     script->len = token - script->token;
 
-    assert(script->len < count);
+    JimPanic((script->len >= count, "allocated script array is too short"));
 
 #ifdef DEBUG_SHOW_SCRIPT
     printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj));
@@ -3348,6 +3560,38 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
 }
 
 /**
+ * Sets an appropriate error message for a missing script/expression terminator.
+ *
+ * Returns JIM_ERR if 'ch' represents an unmatched/missing character.
+ *
+ * Note that a trailing backslash is not considered to be an error.
+ */
+static int JimParseCheckMissing(Jim_Interp *interp, int ch)
+{
+    const char *msg;
+
+    switch (ch) {
+        case '\\':
+        case ' ':
+            return JIM_OK;
+
+        case '[':
+            msg = "unmatched \"[\"";
+            break;
+        case '{':
+            msg = "missing close-brace";
+            break;
+        case '"':
+        default:
+            msg = "missing quote";
+            break;
+    }
+
+    Jim_SetResultString(interp, msg, -1);
+    return JIM_ERR;
+}
+
+/**
  * Similar to ScriptObjAddTokens(), but for subst objects.
  */
 static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
@@ -3373,8 +3617,12 @@ static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
 
 /* This method takes the string representation of an object
  * as a Tcl script, and generates the pre-parsed internal representation
- * of the script. */
-static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result)
+ * of the script.
+ *
+ * On parse error, sets an error message and returns JIM_ERR
+ * (Note: the object is still converted to a script, even if an error occurs)
+ */
+static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 {
     int scriptTextLen;
     const char *scriptText = Jim_GetString(objPtr, &scriptTextLen);
@@ -3382,6 +3630,7 @@ static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct J
     struct ScriptObj *script;
     ParseTokenList tokenlist;
     int line = 1;
+    int retcode = JIM_OK;
 
     /* Try to get information about filename / line number */
     if (objPtr->typePtr == &sourceObjType) {
@@ -3397,27 +3646,23 @@ static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct J
         ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt,
             parser.tline);
     }
-    if (result && parser.missing != ' ') {
-        ScriptTokenListFree(&tokenlist);
-        result->missing = parser.missing;
-        result->line = parser.missingline;
-        return JIM_ERR;
-    }
+
+    retcode = JimParseCheckMissing(interp, parser.missing.ch);
 
     /* Add a final EOF token */
     ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
 
-    /* Create the "real" script tokens from the initial token list */
+    /* Create the "real" script tokens from the parsed tokens */
     script = Jim_Alloc(sizeof(*script));
     memset(script, 0, sizeof(*script));
     script->inUse = 1;
-    script->line = line;
     if (objPtr->typePtr == &sourceObjType) {
         script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
     }
     else {
         script->fileNameObj = interp->emptyObj;
     }
+    script->linenr = parser.missing.line;
     Jim_IncrRefCount(script->fileNameObj);
 
     ScriptObjAddTokens(interp, script, &tokenlist);
@@ -3430,15 +3675,27 @@ static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct J
     Jim_SetIntRepPtr(objPtr, script);
     objPtr->typePtr = &scriptObjType;
 
-    return JIM_OK;
+    return retcode;
 }
 
+/**
+ * Returns NULL if the script failed to parse and leaves
+ * an error message in the interp result.
+ *
+ * Otherwise returns a parsed script object.
+ * (Note: the object is still converted to a script, even if an error occurs)
+ */
 ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
 {
-    struct ScriptObj *script = Jim_GetIntRepPtr(objPtr);
+    if (objPtr == interp->emptyObj) {
+        /* Avoid converting emptyObj to a script. use nullScriptObj instead. */
+        objPtr = interp->nullScriptObj;
+    }
 
-    if (objPtr->typePtr != &scriptObjType || script->substFlags) {
-        SetScriptFromAny(interp, objPtr, NULL);
+    if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
+        if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) {
+            return NULL;
+        }
     }
     return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
 }
@@ -3457,14 +3714,11 @@ static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
         if (cmdPtr->isproc) {
             Jim_DecrRefCount(interp, cmdPtr->u.proc.argListObjPtr);
             Jim_DecrRefCount(interp, cmdPtr->u.proc.bodyObjPtr);
+            Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
             if (cmdPtr->u.proc.staticVars) {
                 Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
                 Jim_Free(cmdPtr->u.proc.staticVars);
             }
-            if (cmdPtr->u.proc.prevCmd) {
-                /* Delete any pushed command too */
-                JimDecrCmdRefCount(interp, cmdPtr->u.proc.prevCmd);
-            }
         }
         else {
             /* native (C) */
@@ -3472,68 +3726,278 @@ static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
                 cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData);
             }
         }
+        if (cmdPtr->prevCmd) {
+            /* Delete any pushed command too */
+            JimDecrCmdRefCount(interp, cmdPtr->prevCmd);
+        }
         Jim_Free(cmdPtr);
     }
 }
 
+/* Variables HashTable Type.
+ *
+ * Keys are dynamically allocated strings, Values are Jim_Var structures.
+ */
+
+/* Variables HashTable Type.
+ *
+ * Keys are dynamic allocated strings, Values are Jim_Var structures. */
+static void JimVariablesHTValDestructor(void *interp, void *val)
+{
+    Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr);
+    Jim_Free(val);
+}
+
+static const Jim_HashTableType JimVariablesHashTableType = {
+    JimStringCopyHTHashFunction,        /* hash function */
+    JimStringCopyHTDup,                 /* key dup */
+    NULL,                               /* val dup */
+    JimStringCopyHTKeyCompare,  /* key compare */
+    JimStringCopyHTKeyDestructor,       /* key destructor */
+    JimVariablesHTValDestructor /* val destructor */
+};
+
 /* Commands HashTable Type.
  *
- * Keys are dynamic allocated strings, Values are Jim_Cmd structures. */
+ * Keys are dynamic allocated strings, Values are Jim_Cmd structures.
+ */
 static void JimCommandsHT_ValDestructor(void *interp, void *val)
 {
     JimDecrCmdRefCount(interp, val);
 }
 
 static const Jim_HashTableType JimCommandsHashTableType = {
-    JimStringCopyHTHashFunction,        /* hash function */
-    JimStringCopyHTKeyDup,      /* key dup */
-    NULL,                       /* val dup */
-    JimStringCopyHTKeyCompare,  /* key compare */
-    JimStringCopyHTKeyDestructor,       /* key destructor */
-    JimCommandsHT_ValDestructor        /* val destructor */
+    JimStringCopyHTHashFunction,    /* hash function */
+    JimStringCopyHTDup,             /* key dup */
+    NULL,                           /* val dup */
+    JimStringCopyHTKeyCompare,      /* key compare */
+    JimStringCopyHTKeyDestructor,   /* key destructor */
+    JimCommandsHT_ValDestructor     /* val destructor */
 };
 
 /* ------------------------- Commands related functions --------------------- */
 
-int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName,
-    Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc)
+#ifdef jim_ext_namespace
+/**
+ * Returns the "unscoped" version of the given namespace.
+ * That is, the fully qualfied name without the leading ::
+ * The returned value is either nsObj, or an object with a zero ref count.
+ */
+static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj)
 {
-    Jim_Cmd *cmdPtr;
+    const char *name = Jim_String(nsObj);
+    if (name[0] == ':' && name[1] == ':') {
+        /* This command is being defined in the global namespace */
+        while (*++name == ':') {
+        }
+        nsObj = Jim_NewStringObj(interp, name, -1);
+    }
+    else if (Jim_Length(interp->framePtr->nsObj)) {
+        /* This command is being defined in a non-global namespace */
+        nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
+        Jim_AppendStrings(interp, nsObj, "::", name, NULL);
+    }
+    return nsObj;
+}
 
-    if (Jim_DeleteHashEntry(&interp->commands, cmdName) != JIM_ERR) {
-        /* Command existed so incr proc epoch */
+Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
+{
+    Jim_Obj *resultObj;
+
+    const char *name = Jim_String(nameObjPtr);
+    if (name[0] == ':' && name[1] == ':') {
+        return nameObjPtr;
+    }
+    Jim_IncrRefCount(nameObjPtr);
+    resultObj = Jim_NewStringObj(interp, "::", -1);
+    Jim_AppendObj(interp, resultObj, nameObjPtr);
+    Jim_DecrRefCount(interp, nameObjPtr);
+
+    return resultObj;
+}
+
+/**
+ * An efficient version of JimQualifyNameObj() where the name is
+ * available (and needed) as a 'const char *'.
+ * Avoids creating an object if not necessary.
+ * The object stored in *objPtrPtr should be disposed of with JimFreeQualifiedName() after use.
+ */
+static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr)
+{
+    Jim_Obj *objPtr = interp->emptyObj;
+
+    if (name[0] == ':' && name[1] == ':') {
+        /* This command is being defined in the global namespace */
+        while (*++name == ':') {
+        }
+    }
+    else if (Jim_Length(interp->framePtr->nsObj)) {
+        /* This command is being defined in a non-global namespace */
+        objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
+        Jim_AppendStrings(interp, objPtr, "::", name, NULL);
+        name = Jim_String(objPtr);
+    }
+    Jim_IncrRefCount(objPtr);
+    *objPtrPtr = objPtr;
+    return name;
+}
+
+    #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ))
+
+#else
+    /* We can be more efficient in the no-namespace case */
+    #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME))
+    #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY)
+
+Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr)
+{
+    return nameObjPtr;
+}
+#endif
+
+static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
+{
+    /* It may already exist, so we try to delete the old one.
+     * Note that reference count means that it won't be deleted yet if
+     * it exists in the call stack.
+     *
+     * BUT, if 'local' is in force, instead of deleting the existing
+     * proc, we stash a reference to the old proc here.
+     */
+    Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name);
+    if (he) {
+        /* There was an old cmd with the same name,
+         * so this requires a 'proc epoch' update. */
+
+        /* If a procedure with the same name didn't exist there is no need
+         * to increment the 'proc epoch' because creation of a new procedure
+         * can never affect existing cached commands. We don't do
+         * negative caching. */
         Jim_InterpIncrProcEpoch(interp);
     }
 
-    cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
+    if (he && interp->local) {
+        /* Push this command over the top of the previous one */
+        cmd->prevCmd = Jim_GetHashEntryVal(he);
+        Jim_SetHashVal(&interp->commands, he, cmd);
+    }
+    else {
+        if (he) {
+            /* Replace the existing command */
+            Jim_DeleteHashEntry(&interp->commands, name);
+        }
 
-    /* Store the new details for this proc */
+        Jim_AddHashEntry(&interp->commands, name, cmd);
+    }
+    return JIM_OK;
+}
+
+
+int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
+    Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc)
+{
+    Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
+
+    /* Store the new details for this command */
     memset(cmdPtr, 0, sizeof(*cmdPtr));
     cmdPtr->inUse = 1;
     cmdPtr->u.native.delProc = delProc;
     cmdPtr->u.native.cmdProc = cmdProc;
     cmdPtr->u.native.privData = privData;
 
-    Jim_AddHashEntry(&interp->commands, cmdName, cmdPtr);
+    JimCreateCommand(interp, cmdNameStr, cmdPtr);
+
+    return JIM_OK;
+}
+
+static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *staticsListObjPtr)
+{
+    int len, i;
+
+    len = Jim_ListLength(interp, staticsListObjPtr);
+    if (len == 0) {
+        return JIM_OK;
+    }
+
+    cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
+    Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
+    for (i = 0; i < len; i++) {
+        Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
+        Jim_Var *varPtr;
+        int subLen;
+
+        objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i);
+        /* Check if it's composed of two elements. */
+        subLen = Jim_ListLength(interp, objPtr);
+        if (subLen == 1 || subLen == 2) {
+            /* Try to get the variable value from the current
+             * environment. */
+            nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0);
+            if (subLen == 1) {
+                initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
+                if (initObjPtr == NULL) {
+                    Jim_SetResultFormatted(interp,
+                        "variable for initialization of static \"%#s\" not found in the local context",
+                        nameObjPtr);
+                    return JIM_ERR;
+                }
+            }
+            else {
+                initObjPtr = Jim_ListGetIndex(interp, objPtr, 1);
+            }
+            if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
+                return JIM_ERR;
+            }
 
-    /* There is no need to increment the 'proc epoch' because
-     * creation of a new procedure can never affect existing
-     * cached commands. We don't do negative caching. */
+            varPtr = Jim_Alloc(sizeof(*varPtr));
+            varPtr->objPtr = initObjPtr;
+            Jim_IncrRefCount(initObjPtr);
+            varPtr->linkFramePtr = NULL;
+            if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars,
+                Jim_String(nameObjPtr), varPtr) != JIM_OK) {
+                Jim_SetResultFormatted(interp,
+                    "static variable name \"%#s\" duplicated in statics list", nameObjPtr);
+                Jim_DecrRefCount(interp, initObjPtr);
+                Jim_Free(varPtr);
+                return JIM_ERR;
+            }
+        }
+        else {
+            Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"",
+                objPtr);
+            return JIM_ERR;
+        }
+    }
     return JIM_OK;
 }
 
-static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
-    Jim_Obj *argListObjPtr, Jim_Obj *staticsListObjPtr, Jim_Obj *bodyObjPtr)
+static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname)
+{
+#ifdef jim_ext_namespace
+    if (cmdPtr->isproc) {
+        /* XXX: Really need JimNamespaceSplit() */
+        const char *pt = strrchr(cmdname, ':');
+        if (pt && pt != cmdname && pt[-1] == ':') {
+            Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
+            cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1);
+            Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
+
+            if (Jim_FindHashEntry(&interp->commands, pt + 1)) {
+                /* This commands shadows a global command, so a proc epoch update is required */
+                Jim_InterpIncrProcEpoch(interp);
+            }
+        }
+    }
+#endif
+}
+
+static Jim_Cmd *JimCreateProcedureCmd(Jim_Interp *interp, Jim_Obj *argListObjPtr,
+    Jim_Obj *staticsListObjPtr, Jim_Obj *bodyObjPtr, Jim_Obj *nsObj)
 {
     Jim_Cmd *cmdPtr;
-    Jim_HashEntry *he;
     int argListLen;
     int i;
 
-    if (JimValidName(interp, "procedure", cmdName) != JIM_OK) {
-        return JIM_ERR;
-    }
-
     argListLen = Jim_ListLength(interp, argListObjPtr);
 
     /* Allocate space for both the command pointer and the arg list */
@@ -3546,65 +4010,14 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
     cmdPtr->u.proc.bodyObjPtr = bodyObjPtr;
     cmdPtr->u.proc.argsPos = -1;
     cmdPtr->u.proc.arglist = (struct Jim_ProcArg *)(cmdPtr + 1);
+    cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj;
     Jim_IncrRefCount(argListObjPtr);
     Jim_IncrRefCount(bodyObjPtr);
+    Jim_IncrRefCount(cmdPtr->u.proc.nsObj);
 
     /* Create the statics hash table. */
-    if (staticsListObjPtr) {
-        int len, i;
-
-        len = Jim_ListLength(interp, staticsListObjPtr);
-        if (len != 0) {
-            cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable));
-            Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp);
-            for (i = 0; i < len; i++) {
-                Jim_Obj *objPtr = 0, *initObjPtr = 0, *nameObjPtr = 0;
-                Jim_Var *varPtr;
-                int subLen;
-
-                Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE);
-                /* Check if it's composed of two elements. */
-                subLen = Jim_ListLength(interp, objPtr);
-                if (subLen == 1 || subLen == 2) {
-                    /* Try to get the variable value from the current
-                     * environment. */
-                    Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE);
-                    if (subLen == 1) {
-                        initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
-                        if (initObjPtr == NULL) {
-                            Jim_SetResultFormatted(interp,
-                                "variable for initialization of static \"%#s\" not found in the local context",
-                                nameObjPtr);
-                            goto err;
-                        }
-                    }
-                    else {
-                        Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE);
-                    }
-                    if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) {
-                        goto err;
-                    }
-
-                    varPtr = Jim_Alloc(sizeof(*varPtr));
-                    varPtr->objPtr = initObjPtr;
-                    Jim_IncrRefCount(initObjPtr);
-                    varPtr->linkFramePtr = NULL;
-                    if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars,
-                        Jim_String(nameObjPtr), varPtr) != JIM_OK) {
-                        Jim_SetResultFormatted(interp,
-                            "static variable name \"%#s\" duplicated in statics list", nameObjPtr);
-                        Jim_DecrRefCount(interp, initObjPtr);
-                        Jim_Free(varPtr);
-                        goto err;
-                    }
-                }
-                else {
-                    Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"",
-                        objPtr);
-                    goto err;
-                }
-            }
-        }
+    if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) {
+        goto err;
     }
 
     /* Parse the args out into arglist, validating as we go */
@@ -3614,24 +4027,25 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
         Jim_Obj *nameObjPtr;
         Jim_Obj *defaultObjPtr;
         int len;
-        int n = 1;
 
         /* Examine a parameter */
-        Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE);
+        argPtr = Jim_ListGetIndex(interp, argListObjPtr, i);
         len = Jim_ListLength(interp, argPtr);
         if (len == 0) {
-            Jim_SetResultString(interp, "procedure has argument with no name", -1);
-            goto err;
+            Jim_SetResultString(interp, "argument with no name", -1);
+err:
+            JimDecrCmdRefCount(interp, cmdPtr);
+            return NULL;
         }
         if (len > 2) {
-            Jim_SetResultString(interp, "procedure has argument with too many fields", -1);
+            Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr);
             goto err;
         }
 
         if (len == 2) {
             /* Optional parameter */
-            Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE);
-            Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE);
+            nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0);
+            defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1);
         }
         else {
             /* Required parameter */
@@ -3642,17 +4056,17 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
 
         if (Jim_CompareStringImmediate(interp, nameObjPtr, "args")) {
             if (cmdPtr->u.proc.argsPos >= 0) {
-                Jim_SetResultString(interp, "procedure has 'args' specified more than once", -1);
+                Jim_SetResultString(interp, "'args' specified more than once", -1);
                 goto err;
             }
             cmdPtr->u.proc.argsPos = i;
         }
         else {
             if (len == 2) {
-                cmdPtr->u.proc.optArity += n;
+                cmdPtr->u.proc.optArity++;
             }
             else {
-                cmdPtr->u.proc.reqArity += n;
+                cmdPtr->u.proc.reqArity++;
             }
         }
 
@@ -3660,131 +4074,99 @@ static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName,
         cmdPtr->u.proc.arglist[i].defaultObjPtr = defaultObjPtr;
     }
 
-    /* Add the new command */
-
-    /* It may already exist, so we try to delete the old one.
-     * Note that reference count means that it won't be deleted yet if
-     * it exists in the call stack.
-     *
-     * BUT, if 'local' is in force, instead of deleting the existing
-     * proc, we stash a reference to the old proc here.
-     */
-    he = Jim_FindHashEntry(&interp->commands, Jim_String(cmdName));
-    if (he) {
-        /* There was an old procedure with the same name, this requires
-         * a 'proc epoch' update. */
+    return cmdPtr;
+}
 
-        /* If a procedure with the same name didn't existed there is no need
-         * to increment the 'proc epoch' because creation of a new procedure
-         * can never affect existing cached commands. We don't do
-         * negative caching. */
-        Jim_InterpIncrProcEpoch(interp);
-    }
+int Jim_DeleteCommand(Jim_Interp *interp, const char *name)
+{
+    int ret = JIM_OK;
+    Jim_Obj *qualifiedNameObj;
+    const char *qualname = JimQualifyName(interp, name, &qualifiedNameObj);
 
-    if (he && interp->local) {
-        /* Just push this proc over the top of the previous one */
-        cmdPtr->u.proc.prevCmd = he->u.val;
-        he->u.val = cmdPtr;
+    if (Jim_DeleteHashEntry(&interp->commands, qualname) == JIM_ERR) {
+        Jim_SetResultFormatted(interp, "can't delete \"%s\": command doesn't exist", name);
+        ret = JIM_ERR;
     }
     else {
-        if (he) {
-            /* Replace the existing proc */
-            Jim_DeleteHashEntry(&interp->commands, Jim_String(cmdName));
-        }
-
-        Jim_AddHashEntry(&interp->commands, Jim_String(cmdName), cmdPtr);
+        Jim_InterpIncrProcEpoch(interp);
     }
 
-    /* Unlike Tcl, set the name of the proc as the result */
-    Jim_SetResult(interp, cmdName);
-    return JIM_OK;
-
-  err:
-    if (cmdPtr->u.proc.staticVars) {
-        Jim_FreeHashTable(cmdPtr->u.proc.staticVars);
-    }
-    Jim_Free(cmdPtr->u.proc.staticVars);
-    Jim_DecrRefCount(interp, argListObjPtr);
-    Jim_DecrRefCount(interp, bodyObjPtr);
-    Jim_Free(cmdPtr);
-    return JIM_ERR;
-}
+    JimFreeQualifiedName(interp, qualifiedNameObj);
 
-int Jim_DeleteCommand(Jim_Interp *interp, const char *cmdName)
-{
-    if (Jim_DeleteHashEntry(&interp->commands, cmdName) == JIM_ERR)
-        return JIM_ERR;
-    Jim_InterpIncrProcEpoch(interp);
-    return JIM_OK;
+    return ret;
 }
 
 int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName)
 {
+    int ret = JIM_ERR;
     Jim_HashEntry *he;
+    Jim_Cmd *cmdPtr;
+    Jim_Obj *qualifiedOldNameObj;
+    Jim_Obj *qualifiedNewNameObj;
+    const char *fqold;
+    const char *fqnew;
 
-    /* Does it exist? */
-    he = Jim_FindHashEntry(&interp->commands, oldName);
-    if (he == NULL) {
-        Jim_SetResultFormatted(interp, "can't %s \"%s\": command doesn't exist",
-            newName[0] ? "rename" : "delete", oldName);
-        return JIM_ERR;
+    if (newName[0] == 0) {
+        return Jim_DeleteCommand(interp, oldName);
     }
 
-    if (newName[0] == '\0')     /* Delete! */
-        return Jim_DeleteCommand(interp, oldName);
+    fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj);
+    fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj);
 
-    /* rename */
-    if (Jim_FindHashEntry(&interp->commands, newName)) {
+    /* Does it exist? */
+    he = Jim_FindHashEntry(&interp->commands, fqold);
+    if (he == NULL) {
+        Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName);
+    }
+    else if (Jim_FindHashEntry(&interp->commands, fqnew)) {
         Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName);
-        return JIM_ERR;
     }
+    else {
+        /* Add the new name first */
+        cmdPtr = Jim_GetHashEntryVal(he);
+        JimIncrCmdRefCount(cmdPtr);
+        JimUpdateProcNamespace(interp, cmdPtr, fqnew);
+        Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr);
 
-    /* Add the new name first */
-    JimIncrCmdRefCount(he->u.val);
-    Jim_AddHashEntry(&interp->commands, newName, he->u.val);
+        /* Now remove the old name */
+        Jim_DeleteHashEntry(&interp->commands, fqold);
 
-    /* Now remove the old name */
-    Jim_DeleteHashEntry(&interp->commands, oldName);
+        /* Increment the epoch */
+        Jim_InterpIncrProcEpoch(interp);
 
-    /* Increment the epoch */
-    Jim_InterpIncrProcEpoch(interp);
-    return JIM_OK;
+        ret = JIM_OK;
+    }
+
+    JimFreeQualifiedName(interp, qualifiedOldNameObj);
+    JimFreeQualifiedName(interp, qualifiedNewNameObj);
+
+    return ret;
 }
 
 /* -----------------------------------------------------------------------------
  * Command object
  * ---------------------------------------------------------------------------*/
 
-static int SetCommandFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+static void FreeCommandInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_DecrRefCount(interp, objPtr->internalRep.cmdValue.nsObj);
+}
+
+static void DupCommandInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
+{
+    dupPtr->internalRep.cmdValue = srcPtr->internalRep.cmdValue;
+    dupPtr->typePtr = srcPtr->typePtr;
+    Jim_IncrRefCount(dupPtr->internalRep.cmdValue.nsObj);
+}
 
 static const Jim_ObjType commandObjType = {
     "command",
-    NULL,
-    NULL,
+    FreeCommandInternalRep,
+    DupCommandInternalRep,
     NULL,
     JIM_TYPE_REFERENCES,
 };
 
-int SetCommandFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
-{
-    Jim_HashEntry *he;
-    const char *cmdName;
-
-    /* Get the string representation */
-    cmdName = Jim_String(objPtr);
-    /* Lookup this name into the commands hash table */
-    he = Jim_FindHashEntry(&interp->commands, cmdName);
-    if (he == NULL)
-        return JIM_ERR;
-
-    /* Free the old internal repr and set the new one. */
-    Jim_FreeIntRep(interp, objPtr);
-    objPtr->typePtr = &commandObjType;
-    objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
-    objPtr->internalRep.cmdValue.cmdPtr = (void *)he->u.val;
-    return JIM_OK;
-}
-
 /* This function returns the command structure for the command name
  * stored in objPtr. It tries to specialize the objPtr to contain
  * a cached info instead to perform the lookup into the hash table
@@ -3797,17 +4179,64 @@ Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
 {
     Jim_Cmd *cmd;
 
-    if ((objPtr->typePtr != &commandObjType ||
-            objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch) &&
-        SetCommandFromAny(interp, objPtr) == JIM_ERR) {
-        if (flags & JIM_ERRMSG) {
-            Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
+    /* In order to be valid, the proc epoch must match and
+     * the lookup must have occurred in the same namespace
+     */
+    if (objPtr->typePtr != &commandObjType ||
+            objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch
+#ifdef jim_ext_namespace
+            || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj)
+#endif
+        ) {
+        /* Not cached or out of date, so lookup */
+
+        /* Do we need to try the local namespace? */
+        const char *name = Jim_String(objPtr);
+        Jim_HashEntry *he;
+
+        if (name[0] == ':' && name[1] == ':') {
+            while (*++name == ':') {
+            }
+        }
+#ifdef jim_ext_namespace
+        else if (Jim_Length(interp->framePtr->nsObj)) {
+            /* This command is being defined in a non-global namespace */
+            Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj);
+            Jim_AppendStrings(interp, nameObj, "::", name, NULL);
+            he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj));
+            Jim_FreeNewObj(interp, nameObj);
+            if (he) {
+                goto found;
+            }
+        }
+#endif
+
+        /* Lookup in the global namespace */
+        he = Jim_FindHashEntry(&interp->commands, name);
+        if (he == NULL) {
+            if (flags & JIM_ERRMSG) {
+                Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr);
+            }
+            return NULL;
         }
-        return NULL;
+#ifdef jim_ext_namespace
+found:
+#endif
+        cmd = Jim_GetHashEntryVal(he);
+
+        /* Free the old internal repr and set the new one. */
+        Jim_FreeIntRep(interp, objPtr);
+        objPtr->typePtr = &commandObjType;
+        objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch;
+        objPtr->internalRep.cmdValue.cmdPtr = cmd;
+        objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj;
+        Jim_IncrRefCount(interp->framePtr->nsObj);
+    }
+    else {
+        cmd = objPtr->internalRep.cmdValue.cmdPtr;
     }
-    cmd = objPtr->internalRep.cmdValue.cmdPtr;
-    while (cmd->isproc && cmd->u.proc.upcall) {
-        cmd = cmd->u.proc.prevCmd;
+    while (cmd->u.proc.upcall) {
+        cmd = cmd->prevCmd;
     }
     return cmd;
 }
@@ -3816,26 +4245,6 @@ Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
  * Variables
  * ---------------------------------------------------------------------------*/
 
-/* Variables HashTable Type.
- *
- * Keys are dynamic allocated strings, Values are Jim_Var structures. */
-static void JimVariablesHTValDestructor(void *interp, void *val)
-{
-    Jim_Var *varPtr = (void *)val;
-
-    Jim_DecrRefCount(interp, varPtr->objPtr);
-    Jim_Free(val);
-}
-
-static const Jim_HashTableType JimVariablesHashTableType = {
-    JimStringCopyHTHashFunction,        /* hash function */
-    JimStringCopyHTKeyDup,      /* key dup */
-    NULL,                       /* val dup */
-    JimStringCopyHTKeyCompare,  /* key compare */
-    JimStringCopyHTKeyDestructor,       /* key destructor */
-    JimVariablesHTValDestructor /* val destructor */
-};
-
 /* -----------------------------------------------------------------------------
  * Variable object
  * ---------------------------------------------------------------------------*/
@@ -3852,15 +4261,6 @@ static const Jim_ObjType variableObjType = {
     JIM_TYPE_REFERENCES,
 };
 
-/* Return true if the string "str" looks like syntax sugar for [dict]. I.e.
- * is in the form "varname(key)". */
-static int JimNameIsDictSugar(const char *str, int len)
-{
-    if (len && str[len - 1] == ')' && strchr(str, '(') != NULL)
-        return 1;
-    return 0;
-}
-
 /**
  * Check that the name does not contain embedded nulls.
  *
@@ -3888,56 +4288,65 @@ static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPt
  * character is ')' */
 static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 {
-    Jim_HashEntry *he;
     const char *varName;
+    Jim_CallFrame *framePtr;
+    Jim_HashEntry *he;
+    int global;
     int len;
-    Jim_CallFrame *framePtr = interp->framePtr;
 
     /* Check if the object is already an uptodate variable */
-    if (objPtr->typePtr == &variableObjType &&
-        objPtr->internalRep.varValue.callFrameId == framePtr->id) {
-        return JIM_OK;          /* nothing to do */
+    if (objPtr->typePtr == &variableObjType) {
+        framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr;
+        if (objPtr->internalRep.varValue.callFrameId == framePtr->id) {
+            /* nothing to do */
+            return JIM_OK;
+        }
+        /* Need to re-resolve the variable in the updated callframe */
     }
-
-    if (objPtr->typePtr == &dictSubstObjType) {
+    else if (objPtr->typePtr == &dictSubstObjType) {
         return JIM_DICT_SUGAR;
     }
-
-    if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
+    else if (JimValidName(interp, "variable", objPtr) != JIM_OK) {
         return JIM_ERR;
     }
 
-    /* Get the string representation */
+
     varName = Jim_GetString(objPtr, &len);
 
     /* Make sure it's not syntax glue to get/set dict. */
-    if (JimNameIsDictSugar(varName, len)) {
+    if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) {
         return JIM_DICT_SUGAR;
     }
 
     if (varName[0] == ':' && varName[1] == ':') {
-        framePtr = interp->topFramePtr;
-        he = Jim_FindHashEntry(&framePtr->vars, varName + 2);
-        if (he == NULL) {
-            return JIM_ERR;
+        while (*++varName == ':') {
         }
+        global = 1;
+        framePtr = interp->topFramePtr;
     }
     else {
-        /* Lookup this name into the variables hash table */
-        he = Jim_FindHashEntry(&framePtr->vars, varName);
-        if (he == NULL) {
+        global = 0;
+        framePtr = interp->framePtr;
+    }
+
+    /* Resolve this name in the variables hash table */
+    he = Jim_FindHashEntry(&framePtr->vars, varName);
+    if (he == NULL) {
+        if (!global && framePtr->staticVars) {
             /* Try with static vars. */
-            if (framePtr->staticVars == NULL)
-                return JIM_ERR;
-            if (!(he = Jim_FindHashEntry(framePtr->staticVars, varName)))
-                return JIM_ERR;
+            he = Jim_FindHashEntry(framePtr->staticVars, varName);
+        }
+        if (he == NULL) {
+            return JIM_ERR;
         }
     }
+
     /* Free the old internal repr and set the new one. */
     Jim_FreeIntRep(interp, objPtr);
     objPtr->typePtr = &variableObjType;
     objPtr->internalRep.varValue.callFrameId = framePtr->id;
-    objPtr->internalRep.varValue.varPtr = (void *)he->u.val;
+    objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he);
+    objPtr->internalRep.varValue.global = global;
     return JIM_OK;
 }
 
@@ -3945,6 +4354,44 @@ static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
 static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
 
+static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
+{
+    const char *name;
+    Jim_CallFrame *framePtr;
+    int global;
+
+    /* New variable to create */
+    Jim_Var *var = Jim_Alloc(sizeof(*var));
+
+    var->objPtr = valObjPtr;
+    Jim_IncrRefCount(valObjPtr);
+    var->linkFramePtr = NULL;
+
+    name = Jim_String(nameObjPtr);
+    if (name[0] == ':' && name[1] == ':') {
+        while (*++name == ':') {
+        }
+        framePtr = interp->topFramePtr;
+        global = 1;
+    }
+    else {
+        framePtr = interp->framePtr;
+        global = 0;
+    }
+
+    /* Insert the new variable */
+    Jim_AddHashEntry(&framePtr->vars, name, var);
+
+    /* Make the object int rep a variable */
+    Jim_FreeIntRep(interp, nameObjPtr);
+    nameObjPtr->typePtr = &variableObjType;
+    nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
+    nameObjPtr->internalRep.varValue.varPtr = var;
+    nameObjPtr->internalRep.varValue.global = global;
+
+    return var;
+}
+
 /* For now that's dummy. Variables lookup should be optimized
  * in many ways, with caching of lookups, and possibly with
  * a table of pre-allocated vars in every CallFrame for local vars.
@@ -3953,60 +4400,37 @@ static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
 
 int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
 {
-    const char *name;
-    Jim_Var *var;
     int err;
+    Jim_Var *var;
 
-    if ((err = SetVariableFromAny(interp, nameObjPtr)) != JIM_OK) {
-        Jim_CallFrame *framePtr = interp->framePtr;
-
-        /* Check for [dict] syntax sugar. */
-        if (err == JIM_DICT_SUGAR)
+    switch (SetVariableFromAny(interp, nameObjPtr)) {
+        case JIM_DICT_SUGAR:
             return JimDictSugarSet(interp, nameObjPtr, valObjPtr);
 
-        if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) {
-            return JIM_ERR;
-        }
+        case JIM_ERR:
+            if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) {
+                return JIM_ERR;
+            }
+            JimCreateVariable(interp, nameObjPtr, valObjPtr);
+            break;
 
-        /* New variable to create */
-        name = Jim_String(nameObjPtr);
+        case JIM_OK:
+            var = nameObjPtr->internalRep.varValue.varPtr;
+            if (var->linkFramePtr == NULL) {
+                Jim_IncrRefCount(valObjPtr);
+                Jim_DecrRefCount(interp, var->objPtr);
+                var->objPtr = valObjPtr;
+            }
+            else {                  /* Else handle the link */
+                Jim_CallFrame *savedCallFrame;
 
-        var = Jim_Alloc(sizeof(*var));
-        var->objPtr = valObjPtr;
-        Jim_IncrRefCount(valObjPtr);
-        var->linkFramePtr = NULL;
-        /* Insert the new variable */
-        if (name[0] == ':' && name[1] == ':') {
-            /* Into the top level frame */
-            framePtr = interp->topFramePtr;
-            Jim_AddHashEntry(&framePtr->vars, name + 2, var);
-        }
-        else {
-            Jim_AddHashEntry(&framePtr->vars, name, var);
-        }
-        /* Make the object int rep a variable */
-        Jim_FreeIntRep(interp, nameObjPtr);
-        nameObjPtr->typePtr = &variableObjType;
-        nameObjPtr->internalRep.varValue.callFrameId = framePtr->id;
-        nameObjPtr->internalRep.varValue.varPtr = var;
-    }
-    else {
-        var = nameObjPtr->internalRep.varValue.varPtr;
-        if (var->linkFramePtr == NULL) {
-            Jim_IncrRefCount(valObjPtr);
-            Jim_DecrRefCount(interp, var->objPtr);
-            var->objPtr = valObjPtr;
-        }
-        else {                  /* Else handle the link */
-            Jim_CallFrame *savedCallFrame;
-
-            savedCallFrame = interp->framePtr;
-            interp->framePtr = var->linkFramePtr;
-            err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
-            interp->framePtr = savedCallFrame;
-            if (err != JIM_OK)
-                return err;
-        }
+                savedCallFrame = interp->framePtr;
+                interp->framePtr = var->linkFramePtr;
+                err = Jim_SetVariable(interp, var->objPtr, valObjPtr);
+                interp->framePtr = savedCallFrame;
+                if (err != JIM_OK)
+                    return err;
+            }
     }
     return JIM_OK;
 }
@@ -4054,42 +4478,70 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
     Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame)
 {
     const char *varName;
-    int len;
+    const char *targetName;
+    Jim_CallFrame *framePtr;
+    Jim_Var *varPtr;
+
+    /* Check for an existing variable or link */
+    switch (SetVariableFromAny(interp, nameObjPtr)) {
+        case JIM_DICT_SUGAR:
+            /* XXX: This message seem unnecessarily verbose, but it matches Tcl */
+            Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr);
+            return JIM_ERR;
 
-    varName = Jim_GetString(nameObjPtr, &len);
+        case JIM_OK:
+            varPtr = nameObjPtr->internalRep.varValue.varPtr;
+
+            if (varPtr->linkFramePtr == NULL) {
+                Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
+                return JIM_ERR;
+            }
+
+            /* It exists, but is a link, so first delete the link */
+            varPtr->linkFramePtr = NULL;
+            break;
+    }
+
+    /* Resolve the call frames for both variables */
+    /* XXX: SetVariableFromAny() already did this! */
+    varName = Jim_String(nameObjPtr);
 
     if (varName[0] == ':' && varName[1] == ':') {
+        while (*++varName == ':') {
+        }
         /* Linking a global var does nothing */
-        return JIM_OK;
+        framePtr = interp->topFramePtr;
     }
-
-    if (JimNameIsDictSugar(varName, len)) {
-        Jim_SetResultString(interp, "Dict key syntax invalid as link source", -1);
-        return JIM_ERR;
+    else {
+        framePtr = interp->framePtr;
     }
 
-    /* Check for an existing variable or link */
-    if (SetVariableFromAny(interp, nameObjPtr) == JIM_OK) {
-        Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr;
-
-        if (varPtr->linkFramePtr == NULL) {
-            Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr);
-            return JIM_ERR;
+    targetName = Jim_String(targetNameObjPtr);
+    if (targetName[0] == ':' && targetName[1] == ':') {
+        while (*++targetName == ':') {
         }
+        targetNameObjPtr = Jim_NewStringObj(interp, targetName, -1);
+        targetCallFrame = interp->topFramePtr;
+    }
+    Jim_IncrRefCount(targetNameObjPtr);
 
-        /* It exists, but is a link, so delete the link */
-        varPtr->linkFramePtr = NULL;
+    if (framePtr->level < targetCallFrame->level) {
+        Jim_SetResultFormatted(interp,
+            "bad variable name \"%#s\": upvar won't create namespace variable that refers to procedure variable",
+            nameObjPtr);
+        Jim_DecrRefCount(interp, targetNameObjPtr);
+        return JIM_ERR;
     }
 
     /* Check for cycles. */
-    if (interp->framePtr == targetCallFrame) {
+    if (framePtr == targetCallFrame) {
         Jim_Obj *objPtr = targetNameObjPtr;
-        Jim_Var *varPtr;
 
         /* Cycles are only possible with 'uplevel 0' */
         while (1) {
-            if (Jim_StringEqObj(objPtr, nameObjPtr)) {
+            if (strcmp(Jim_String(objPtr), varName) == 0) {
                 Jim_SetResultString(interp, "can't upvar from variable to itself", -1);
+                Jim_DecrRefCount(interp, targetNameObjPtr);
                 return JIM_ERR;
             }
             if (SetVariableFromAny(interp, objPtr) != JIM_OK)
@@ -4105,6 +4557,7 @@ int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr,
     Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr);
     /* We are now sure 'nameObjPtr' type is variableObjType */
     nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame;
+    Jim_DecrRefCount(interp, targetNameObjPtr);
     return JIM_OK;
 }
 
@@ -4196,9 +4649,9 @@ Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flag
  * in the current call frame incrementing. */
 int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
 {
-    const char *name;
     Jim_Var *varPtr;
     int retval;
+    Jim_CallFrame *framePtr;
 
     retval = SetVariableFromAny(interp, nameObjPtr);
     if (retval == JIM_DICT_SUGAR) {
@@ -4210,25 +4663,25 @@ int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags)
 
         /* If it's a link call UnsetVariable recursively */
         if (varPtr->linkFramePtr) {
-            Jim_CallFrame *savedCallFrame;
-
-            savedCallFrame = interp->framePtr;
+            framePtr = interp->framePtr;
             interp->framePtr = varPtr->linkFramePtr;
             retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE);
-            interp->framePtr = savedCallFrame;
+            interp->framePtr = framePtr;
         }
         else {
-            Jim_CallFrame *framePtr = interp->framePtr;
-
-            name = Jim_String(nameObjPtr);
-            if (name[0] == ':' && name[1] == ':') {
-                framePtr = interp->topFramePtr;
+            const char *name = Jim_String(nameObjPtr);
+            if (nameObjPtr->internalRep.varValue.global) {
                 name += 2;
+                framePtr = interp->topFramePtr;
+            }
+            else {
+                framePtr = interp->framePtr;
             }
+
             retval = Jim_DeleteHashEntry(&framePtr->vars, name);
             if (retval == JIM_OK) {
                 /* Change the callframe id, invalidating var lookup caching */
-                JimChangeCallFrameId(interp, framePtr);
+                framePtr->id = interp->callFrameEpoch++;
             }
         }
     }
@@ -4285,7 +4738,7 @@ static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjP
     SetDictSubstFromAny(interp, objPtr);
 
     err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr,
-        &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_ERRMSG);
+        &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST);
 
     if (err == JIM_OK) {
         /* Don't keep an extra ref to the result */
@@ -4327,24 +4780,13 @@ static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPt
 
     ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
     if (ret != JIM_OK) {
-        resObjPtr = NULL;
-        if (ret < 0) {
-            Jim_SetResultFormatted(interp,
-                "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr);
-        }
-        else {
-            Jim_SetResultFormatted(interp,
-                "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr);
-        }
+        Jim_SetResultFormatted(interp,
+            "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr,
+            ret < 0 ? "variable isn't" : "no such element in");
     }
     else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) {
-        dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr);
-        if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) {
-            /* This can probably never happen */
-            JimPanic((1, "SetVariable failed for JIM_UNSHARED"));
-        }
-        /* We know that the key exists. Get the result in the now-unshared dictionary */
-        Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE);
+        /* Update the variable to have an unshared copy */
+        Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr));
     }
 
     return resObjPtr;
@@ -4387,10 +4829,8 @@ static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
         if (objPtr->typePtr == &interpolatedObjType) {
             /* An interpolated object in dict-sugar form */
 
-            const ScriptToken *token = objPtr->internalRep.twoPtrValue.ptr1;
-
-            varObjPtr = token[0].objPtr;
-            keyObjPtr = objPtr->internalRep.twoPtrValue.ptr2;
+            varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr;
+            keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr;
 
             Jim_IncrRefCount(varObjPtr);
             Jim_IncrRefCount(keyObjPtr);
@@ -4449,48 +4889,95 @@ static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr)
  * CallFrame
  * ---------------------------------------------------------------------------*/
 
-static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent)
+static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj)
 {
     Jim_CallFrame *cf;
 
     if (interp->freeFramesList) {
         cf = interp->freeFramesList;
-        interp->freeFramesList = cf->nextFramePtr;
+        interp->freeFramesList = cf->next;
+
+        cf->argv = NULL;
+        cf->argc = 0;
+        cf->procArgsObjPtr = NULL;
+        cf->procBodyObjPtr = NULL;
+        cf->next = NULL;
+        cf->staticVars = NULL;
+        cf->localCommands = NULL;
+        cf->tailcall = 0;
+        cf->tailcallObj = NULL;
+        cf->tailcallCmd = NULL;
     }
     else {
         cf = Jim_Alloc(sizeof(*cf));
-        cf->vars.table = NULL;
+        memset(cf, 0, sizeof(*cf));
+
+        Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
     }
 
     cf->id = interp->callFrameEpoch++;
-    cf->parentCallFrame = parent;
+    cf->parent = parent;
     cf->level = parent ? parent->level + 1 : 0;
-    cf->argv = NULL;
-    cf->argc = 0;
-    cf->procArgsObjPtr = NULL;
-    cf->procBodyObjPtr = NULL;
-    cf->nextFramePtr = NULL;
-    cf->staticVars = NULL;
-    if (cf->vars.table == NULL)
-        Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp);
+    cf->nsObj = nsObj;
+    Jim_IncrRefCount(nsObj);
+
     return cf;
 }
 
-/* Used to invalidate every caching related to callframe stability. */
-static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf)
+static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands)
 {
-    cf->id = interp->callFrameEpoch++;
+    /* Delete any local procs */
+    if (localCommands) {
+        Jim_Obj *cmdNameObj;
+
+        while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) {
+            Jim_HashEntry *he;
+            Jim_Obj *fqObjName;
+            Jim_HashTable *ht = &interp->commands;
+
+            const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName);
+
+            he = Jim_FindHashEntry(ht, fqname);
+
+            if (he) {
+                Jim_Cmd *cmd = Jim_GetHashEntryVal(he);
+                if (cmd->prevCmd) {
+                    Jim_Cmd *prevCmd = cmd->prevCmd;
+                    cmd->prevCmd = NULL;
+
+                    /* Delete the old command */
+                    JimDecrCmdRefCount(interp, cmd);
+
+                    /* And restore the original */
+                    Jim_SetHashVal(ht, he, prevCmd);
+                }
+                else {
+                    Jim_DeleteHashEntry(ht, fqname);
+                    Jim_InterpIncrProcEpoch(interp);
+                }
+            }
+            Jim_DecrRefCount(interp, cmdNameObj);
+            JimFreeQualifiedName(interp, fqObjName);
+        }
+        Jim_FreeStack(localCommands);
+        Jim_Free(localCommands);
+    }
+    return JIM_OK;
 }
 
-#define JIM_FCF_NONE 0          /* no flags */
-#define JIM_FCF_NOHT 1          /* don't free the hash table */
-static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
-{
+
+#define JIM_FCF_FULL 0          /* Always free the vars hash table */
+#define JIM_FCF_REUSE 1         /* Reuse the vars hash table if possible */
+static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action)
+ {
+    JimDeleteLocalProcs(interp, cf->localCommands);
+
     if (cf->procArgsObjPtr)
         Jim_DecrRefCount(interp, cf->procArgsObjPtr);
     if (cf->procBodyObjPtr)
         Jim_DecrRefCount(interp, cf->procBodyObjPtr);
-    if (!(flags & JIM_FCF_NOHT))
+    Jim_DecrRefCount(interp, cf->nsObj);
+    if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE)
         Jim_FreeHashTable(&cf->vars);
     else {
         int i;
@@ -4500,11 +4987,11 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
             he = table[i];
             while (he != NULL) {
                 Jim_HashEntry *nextEntry = he->next;
-                Jim_Var *varPtr = (void *)he->u.val;
+                Jim_Var *varPtr = Jim_GetHashEntryVal(he);
 
                 Jim_DecrRefCount(interp, varPtr->objPtr);
-                Jim_Free(he->u.val);
-                Jim_Free((void *)he->key);      /* ATTENTION: const cast */
+                Jim_Free(Jim_GetHashEntryKey(he));
+                Jim_Free(varPtr);
                 Jim_Free(he);
                 table[i] = NULL;
                 he = nextEntry;
@@ -4512,10 +4999,11 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
         }
         cf->vars.used = 0;
     }
-    cf->nextFramePtr = interp->freeFramesList;
+    cf->next = interp->freeFramesList;
     interp->freeFramesList = cf;
 }
 
+
 /* -----------------------------------------------------------------------------
  * References
  * ---------------------------------------------------------------------------*/
@@ -4523,8 +5011,8 @@ static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags)
 
 /* References HashTable Type.
  *
- * Keys are jim_wide integers, dynamically allocated for now but in the
- * future it's worth to cache this 8 bytes objects. Values are poitners
+ * Keys are unsigned long integers, dynamically allocated for now but in the
+ * future it's worth to cache this 4 bytes objects. Values are pointers
  * to Jim_References. */
 static void JimReferencesHTValDestructor(void *interp, void *val)
 {
@@ -4540,19 +5028,19 @@ static void JimReferencesHTValDestructor(void *interp, void *val)
 static unsigned int JimReferencesHTHashFunction(const void *key)
 {
     /* Only the least significant bits are used. */
-    const jim_wide *widePtr = key;
+    const unsigned long *widePtr = key;
     unsigned int intValue = (unsigned int)*widePtr;
 
     return Jim_IntHashFunction(intValue);
 }
 
-static const void *JimReferencesHTKeyDup(void *privdata, const void *key)
+static void *JimReferencesHTKeyDup(void *privdata, const void *key)
 {
-    void *copy = Jim_Alloc(sizeof(jim_wide));
+    void *copy = Jim_Alloc(sizeof(unsigned long));
 
     JIM_NOTUSED(privdata);
 
-    memcpy(copy, key, sizeof(jim_wide));
+    memcpy(copy, key, sizeof(unsigned long));
     return copy;
 }
 
@@ -4560,14 +5048,14 @@ static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const voi
 {
     JIM_NOTUSED(privdata);
 
-    return memcmp(key1, key2, sizeof(jim_wide)) == 0;
+    return memcmp(key1, key2, sizeof(unsigned long)) == 0;
 }
 
-static void JimReferencesHTKeyDestructor(void *privdata, const void *key)
+static void JimReferencesHTKeyDestructor(void *privdata, void *key)
 {
     JIM_NOTUSED(privdata);
 
-    Jim_Free((void *)key);
+    Jim_Free(key);
 }
 
 static const Jim_HashTableType JimReferencesHashTableType = {
@@ -4587,14 +5075,14 @@ static const Jim_HashTableType JimReferencesHashTableType = {
  * to make the GC faster. The first is that every reference starts
  * with a non common character '<', in order to make the string matching
  * faster. The second is that the reference string rep is 42 characters
- * in length, this allows to avoid to check every object with a string
+ * in length, this means that it is not necessary to check any object with a string
  * repr < 42, and usually there aren't many of these objects. */
 
 #define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)
 
-static int JimFormatReference(char *buf, Jim_Reference *refPtr, jim_wide id)
+static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id)
 {
-    const char *fmt = "<reference.<%s>.%020" JIM_WIDE_MODIFIER ">";
+    const char *fmt = "<reference.<%s>.%020lu>";
 
     sprintf(buf, fmt, refPtr->tag, id);
     return JIM_REFERENCE_SPACE;
@@ -4610,17 +5098,12 @@ static const Jim_ObjType referenceObjType = {
     JIM_TYPE_REFERENCES,
 };
 
-void UpdateStringOfReference(struct Jim_Obj *objPtr)
+static void UpdateStringOfReference(struct Jim_Obj *objPtr)
 {
-    int len;
     char buf[JIM_REFERENCE_SPACE + 1];
-    Jim_Reference *refPtr;
 
-    refPtr = objPtr->internalRep.refValue.refPtr;
-    len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id);
-    objPtr->bytes = Jim_Alloc(len + 1);
-    memcpy(objPtr->bytes, buf, len + 1);
-    objPtr->length = len;
+    JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id);
+    JimSetStringBytes(objPtr, buf);
 }
 
 /* returns true if 'c' is a valid reference tag character.
@@ -4632,12 +5115,13 @@ static int isrefchar(int c)
 
 static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 {
-    jim_wide wideValue;
+    unsigned long value;
     int i, len;
     const char *str, *start, *end;
     char refId[21];
     Jim_Reference *refPtr;
     Jim_HashEntry *he;
+    char *endptr;
 
     /* Get the string representation */
     str = Jim_GetString(objPtr, &len);
@@ -4666,20 +5150,21 @@ static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
     /* Extract info from the reference. */
     memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20);
     refId[20] = '\0';
-    /* Try to convert the ID into a jim_wide */
-    if (Jim_StringToWide(refId, &wideValue, 10) != JIM_OK)
+    /* Try to convert the ID into an unsigned long */
+    value = strtoul(refId, &endptr, 10);
+    if (JimCheckConversion(refId, endptr) != JIM_OK)
         goto badformat;
     /* Check if the reference really exists! */
-    he = Jim_FindHashEntry(&interp->references, &wideValue);
+    he = Jim_FindHashEntry(&interp->references, &value);
     if (he == NULL) {
         Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr);
         return JIM_ERR;
     }
-    refPtr = he->u.val;
+    refPtr = Jim_GetHashEntryVal(he);
     /* Free the old internal repr and set the new one. */
     Jim_FreeIntRep(interp, objPtr);
     objPtr->typePtr = &referenceObjType;
-    objPtr->internalRep.refValue.id = wideValue;
+    objPtr->internalRep.refValue.id = value;
     objPtr->internalRep.refValue.refPtr = refPtr;
     return JIM_OK;
 
@@ -4694,7 +5179,7 @@ static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr)
 {
     struct Jim_Reference *refPtr;
-    jim_wide wideValue = interp->referenceNextId;
+    unsigned long id;
     Jim_Obj *refObjPtr;
     const char *tag;
     int tagLen, i;
@@ -4708,11 +5193,12 @@ Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr,
     refPtr->finalizerCmdNamePtr = cmdNamePtr;
     if (cmdNamePtr)
         Jim_IncrRefCount(cmdNamePtr);
-    Jim_AddHashEntry(&interp->references, &wideValue, refPtr);
+    id = interp->referenceNextId++;
+    Jim_AddHashEntry(&interp->references, &id, refPtr);
     refObjPtr = Jim_NewObj(interp);
     refObjPtr->typePtr = &referenceObjType;
     refObjPtr->bytes = NULL;
-    refObjPtr->internalRep.refValue.id = interp->referenceNextId;
+    refObjPtr->internalRep.refValue.id = id;
     refObjPtr->internalRep.refValue.refPtr = refPtr;
     interp->referenceNextId++;
     /* Set the tag. Trimmed at JIM_REFERENCE_TAGLEN. Everything
@@ -4780,7 +5266,7 @@ int Jim_Collect(Jim_Interp *interp)
     int collected = 0;
 #ifndef JIM_BOOTSTRAP
     Jim_HashTable marks;
-    Jim_HashTableIterator *htiter;
+    Jim_HashTableIterator htiter;
     Jim_HashEntry *he;
     Jim_Obj *objPtr;
 
@@ -4806,7 +5292,7 @@ int Jim_Collect(Jim_Interp *interp)
             if (objPtr->typePtr == &referenceObjType) {
                 Jim_AddHashEntry(&marks, &objPtr->internalRep.refValue.id, NULL);
 #ifdef JIM_DEBUG_GC
-                printf("MARK (reference): %d refcount: %d" JIM_NL,
+                printf("MARK (reference): %d refcount: %d\n",
                     (int)objPtr->internalRep.refValue.id, objPtr->refCount);
 #endif
                 objPtr = objPtr->nextObjPtr;
@@ -4823,8 +5309,7 @@ int Jim_Collect(Jim_Interp *interp)
             /* Extract references from the object string repr. */
             while (1) {
                 int i;
-                jim_wide id;
-                char buf[21];
+                unsigned long id;
 
                 if ((p = strstr(p, "<reference.<")) == NULL)
                     break;
@@ -4837,15 +5322,13 @@ int Jim_Collect(Jim_Interp *interp)
                     if (!isdigit(UCHAR(p[i])))
                         break;
                 /* Get the ID */
-                memcpy(buf, p + 21, 20);
-                buf[20] = '\0';
-                Jim_StringToWide(buf, &id, 10);
+                id = strtoul(p + 21, NULL, 10);
 
                 /* Ok, a reference for the given ID
                  * was found. Mark it. */
                 Jim_AddHashEntry(&marks, &id, NULL);
 #ifdef JIM_DEBUG_GC
-                printf("MARK: %d" JIM_NL, (int)id);
+                printf("MARK: %d\n", (int)id);
 #endif
                 p += JIM_REFERENCE_SPACE;
             }
@@ -4855,9 +5338,9 @@ int Jim_Collect(Jim_Interp *interp)
 
     /* Run the references hash table to destroy every reference that
      * is not referenced outside (not present in the mark HT). */
-    htiter = Jim_GetHashTableIterator(&interp->references);
-    while ((he = Jim_NextHashEntry(htiter)) != NULL) {
-        const jim_wide *refId;
+    JimInitHashTableIterator(&interp->references, &htiter);
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        const unsigned long *refId;
         Jim_Reference *refPtr;
 
         refId = he->key;
@@ -4865,12 +5348,12 @@ int Jim_Collect(Jim_Interp *interp)
          * this reference. */
         if (Jim_FindHashEntry(&marks, refId) == NULL) {
 #ifdef JIM_DEBUG_GC
-            printf("COLLECTING %d" JIM_NL, (int)*refId);
+            printf("COLLECTING %d\n", (int)*refId);
 #endif
             collected++;
             /* Drop the reference, but call the
              * finalizer first if registered. */
-            refPtr = he->u.val;
+            refPtr = Jim_GetHashEntryVal(he);
             if (refPtr->finalizerCmdNamePtr) {
                 char *refstr = Jim_Alloc(JIM_REFERENCE_SPACE + 1);
                 Jim_Obj *objv[3], *oldResult;
@@ -4878,16 +5361,17 @@ int Jim_Collect(Jim_Interp *interp)
                 JimFormatReference(refstr, refPtr, *refId);
 
                 objv[0] = refPtr->finalizerCmdNamePtr;
-                objv[1] = Jim_NewStringObjNoAlloc(interp, refstr, 32);
+                objv[1] = Jim_NewStringObjNoAlloc(interp, refstr, JIM_REFERENCE_SPACE);
                 objv[2] = refPtr->objPtr;
-                Jim_IncrRefCount(objv[0]);
-                Jim_IncrRefCount(objv[1]);
-                Jim_IncrRefCount(objv[2]);
 
                 /* Drop the reference itself */
-                Jim_DeleteHashEntry(&interp->references, refId);
+                /* Avoid the finaliser being freed here */
+                Jim_IncrRefCount(objv[0]);
+                /* Don't remove the reference from the hash table just yet
+                 * since that will free refPtr, and hence refPtr->objPtr
+                 */
 
-                /* Call the finalizer. Errors ignored. */
+                /* Call the finalizer. Errors ignored. (should we use bgerror?) */
                 oldResult = interp->result;
                 Jim_IncrRefCount(oldResult);
                 Jim_EvalObjVector(interp, 3, objv);
@@ -4895,15 +5379,10 @@ int Jim_Collect(Jim_Interp *interp)
                 Jim_DecrRefCount(interp, oldResult);
 
                 Jim_DecrRefCount(interp, objv[0]);
-                Jim_DecrRefCount(interp, objv[1]);
-                Jim_DecrRefCount(interp, objv[2]);
-            }
-            else {
-                Jim_DeleteHashEntry(&interp->references, refId);
             }
+            Jim_DeleteHashEntry(&interp->references, refId);
         }
     }
-    Jim_FreeHashTableIterator(htiter);
     Jim_FreeHashTable(&marks);
     interp->lastCollectId = interp->referenceNextId;
     interp->lastCollectTime = time(NULL);
@@ -4916,7 +5395,7 @@ int Jim_Collect(Jim_Interp *interp)
 
 void Jim_CollectIfNeeded(Jim_Interp *interp)
 {
-    jim_wide elapsedId;
+    unsigned long elapsedId;
     int elapsedTime;
 
     elapsedId = interp->referenceNextId - interp->lastCollectId;
@@ -4929,7 +5408,7 @@ void Jim_CollectIfNeeded(Jim_Interp *interp)
 }
 #endif
 
-static int JimIsBigEndian(void)
+int Jim_IsBigEndian(void)
 {
     union {
         unsigned short s;
@@ -4949,7 +5428,8 @@ Jim_Interp *Jim_CreateInterp(void)
 
     memset(i, 0, sizeof(*i));
 
-    i->maxNestingDepth = JIM_MAX_NESTING_DEPTH;
+    i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH;
+    i->maxEvalDepth = JIM_MAX_EVAL_DEPTH;
     i->lastCollectTime = time(NULL);
 
     /* Note that we can create objects only after the
@@ -4960,23 +5440,25 @@ Jim_Interp *Jim_CreateInterp(void)
     Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i);
 #endif
     Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i);
-    Jim_InitHashTable(&i->packages, &JimStringKeyValCopyHashTableType, NULL);
-    i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL);
+    Jim_InitHashTable(&i->packages, &JimPackageHashTableType, NULL);
     i->emptyObj = Jim_NewEmptyStringObj(i);
     i->trueObj = Jim_NewIntObj(i, 1);
     i->falseObj = Jim_NewIntObj(i, 0);
+    i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL, i->emptyObj);
     i->errorFileNameObj = i->emptyObj;
     i->result = i->emptyObj;
     i->stackTrace = Jim_NewListObj(i, NULL, 0);
     i->unknown = Jim_NewStringObj(i, "unknown", -1);
     i->errorProc = i->emptyObj;
     i->currentScriptObj = Jim_NewEmptyStringObj(i);
+    i->nullScriptObj = Jim_NewEmptyStringObj(i);
     Jim_IncrRefCount(i->emptyObj);
     Jim_IncrRefCount(i->errorFileNameObj);
     Jim_IncrRefCount(i->result);
     Jim_IncrRefCount(i->stackTrace);
     Jim_IncrRefCount(i->unknown);
     Jim_IncrRefCount(i->currentScriptObj);
+    Jim_IncrRefCount(i->nullScriptObj);
     Jim_IncrRefCount(i->errorProc);
     Jim_IncrRefCount(i->trueObj);
     Jim_IncrRefCount(i->falseObj);
@@ -4988,7 +5470,7 @@ Jim_Interp *Jim_CreateInterp(void)
     Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
     Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
     Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
-    Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", JimIsBigEndian() ? "bigEndian" : "littleEndian");
+    Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian");
     Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0");
     Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
     Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));
@@ -4998,9 +5480,16 @@ Jim_Interp *Jim_CreateInterp(void)
 
 void Jim_FreeInterp(Jim_Interp *i)
 {
-    Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf;
+    Jim_CallFrame *cf, *cfx;
+
     Jim_Obj *objPtr, *nextObjPtr;
 
+    /* Free the active call frames list - must be done before i->commands is destroyed */
+    for (cf = i->framePtr; cf; cf = cfx) {
+        cfx = cf->parent;
+        JimFreeCallFrame(i, cf, JIM_FCF_FULL);
+    }
+
     Jim_DecrRefCount(i, i->emptyObj);
     Jim_DecrRefCount(i, i->trueObj);
     Jim_DecrRefCount(i, i->falseObj);
@@ -5010,6 +5499,7 @@ void Jim_FreeInterp(Jim_Interp *i)
     Jim_DecrRefCount(i, i->unknown);
     Jim_DecrRefCount(i, i->errorFileNameObj);
     Jim_DecrRefCount(i, i->currentScriptObj);
+    Jim_DecrRefCount(i, i->nullScriptObj);
     Jim_FreeHashTable(&i->commands);
 #ifdef JIM_REFERENCES
     Jim_FreeHashTable(&i->references);
@@ -5017,36 +5507,38 @@ void Jim_FreeInterp(Jim_Interp *i)
     Jim_FreeHashTable(&i->packages);
     Jim_Free(i->prngState);
     Jim_FreeHashTable(&i->assocData);
-    JimDeleteLocalProcs(i);
 
-    /* Free the call frames list */
-    while (cf) {
-        prevcf = cf->parentCallFrame;
-        JimFreeCallFrame(i, cf, JIM_FCF_NONE);
-        cf = prevcf;
-    }
     /* Check that the live object list is empty, otherwise
      * there is a memory leak. */
+#ifdef JIM_MAINTAINER
     if (i->liveList != NULL) {
         objPtr = i->liveList;
 
-        printf(JIM_NL "-------------------------------------" JIM_NL);
-        printf("Objects still in the free list:" JIM_NL);
+        printf("\n-------------------------------------\n");
+        printf("Objects still in the free list:\n");
         while (objPtr) {
             const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string";
 
-            printf("%p (%d) %-10s: '%.20s'" JIM_NL,
-                (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
+            if (objPtr->bytes && strlen(objPtr->bytes) > 20) {
+                printf("%p (%d) %-10s: '%.20s...'\n",
+                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes);
+            }
+            else {
+                printf("%p (%d) %-10s: '%s'\n",
+                    (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)");
+            }
             if (objPtr->typePtr == &sourceObjType) {
-                printf("FILE %s LINE %d" JIM_NL,
+                printf("FILE %s LINE %d\n",
                     Jim_String(objPtr->internalRep.sourceValue.fileNameObj),
                     objPtr->internalRep.sourceValue.lineNumber);
             }
             objPtr = objPtr->nextObjPtr;
         }
-        printf("-------------------------------------" JIM_NL JIM_NL);
+        printf("-------------------------------------\n\n");
         JimPanic((1, "Live list non empty freeing the interpreter! Leak?"));
     }
+#endif
+
     /* Free all the freed objects. */
     objPtr = i->freeList;
     while (objPtr) {
@@ -5054,34 +5546,29 @@ void Jim_FreeInterp(Jim_Interp *i)
         Jim_Free(objPtr);
         objPtr = nextObjPtr;
     }
-    /* Free cached CallFrame structures */
-    cf = i->freeFramesList;
-    while (cf) {
-        nextcf = cf->nextFramePtr;
-        if (cf->vars.table != NULL)
-            Jim_Free(cf->vars.table);
+
+    /* Free the free call frames list */
+    for (cf = i->freeFramesList; cf; cf = cfx) {
+        cfx = cf->next;
+        if (cf->vars.table)
+            Jim_FreeHashTable(&cf->vars);
         Jim_Free(cf);
-        cf = nextcf;
     }
-#ifdef jim_ext_load
-    Jim_FreeLoadHandles(i);
-#endif
 
     /* Free the interpreter structure. */
     Jim_Free(i);
 }
 
 /* Returns the call frame relative to the level represented by
- * levelObjPtr. If levelObjPtr == NULL, the level is assumed to be '1'.
+ * levelObjPtr. If levelObjPtr == NULL, the level is assumed to be '1'.
  *
  * This function accepts the 'level' argument in the form
  * of the commands [uplevel] and [upvar].
  *
- * For a function accepting a relative integer as level suitable
- * for implementation of [info level ?level?] check the
- * JimGetCallFrameByInteger() function.
- *
  * Returns NULL on error.
+ *
+ * Note: for a function accepting a relative integer as level suitable
+ * for implementation of [info level ?level?], see JimGetCallFrameByInteger()
  */
 Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
 {
@@ -5094,7 +5581,7 @@ Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
         if (str[0] == '#') {
             char *endptr;
 
-            level = strtol(str + 1, &endptr, 0);
+            level = jim_strtol(str + 1, &endptr);
             if (str[1] == '\0' || endptr[0] != '\0') {
                 level = -1;
             }
@@ -5119,7 +5606,7 @@ Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr)
     }
     if (level > 0) {
         /* Lookup */
-        for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) {
+        for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
             if (framePtr->level == level) {
                 return framePtr;
             }
@@ -5149,7 +5636,7 @@ static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *leve
         }
 
         /* Lookup */
-        for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) {
+        for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) {
             if (framePtr->level == level) {
                 return framePtr;
             }
@@ -5183,19 +5670,12 @@ static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
      */
     len = Jim_ListLength(interp, interp->stackTrace);
     if (len >= 3) {
-        Jim_Obj *filenameObj;
-
-        Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj, JIM_NONE);
-
-        Jim_GetString(filenameObj, &len);
-
-        if (!Jim_Length(filenameObj)) {
+        if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) {
             interp->addStackTrace = 1;
         }
     }
 }
 
-/* Returns 1 if the stack trace information was used or 0 if not */
 static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
     Jim_Obj *fileNameObj, int linenr)
 {
@@ -5219,10 +5699,11 @@ static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
         int len = Jim_ListLength(interp, interp->stackTrace);
 
         if (len >= 3) {
-            Jim_Obj *objPtr;
-            if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) {
+            Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
+            if (Jim_Length(objPtr)) {
                 /* Yes, the previous level had procname */
-                if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) {
+                objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
+                if (Jim_Length(objPtr) == 0) {
                     /* But no filename, so merge the new info with that frame */
                     ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
                     ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
@@ -5252,8 +5733,7 @@ void *Jim_GetAssocData(Jim_Interp *interp, const char *key)
     Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key);
 
     if (entryPtr != NULL) {
-        AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val;
-
+        AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr);
         return assocEntryPtr->data;
     }
     return NULL;
@@ -5272,8 +5752,6 @@ int Jim_GetExitCode(Jim_Interp *interp)
 /* -----------------------------------------------------------------------------
  * Integer object
  * ---------------------------------------------------------------------------*/
-#define JIM_INTEGER_SPACE 24
-
 static void UpdateStringOfInt(struct Jim_Obj *objPtr);
 static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
 
@@ -5299,18 +5777,46 @@ static const Jim_ObjType coercedDoubleObjType = {
 };
 
 
-void UpdateStringOfInt(struct Jim_Obj *objPtr)
+static void UpdateStringOfInt(struct Jim_Obj *objPtr)
 {
-    int len;
     char buf[JIM_INTEGER_SPACE + 1];
+    jim_wide wideValue = JimWideValue(objPtr);
+    int pos = 0;
 
-    len = Jim_WideToString(buf, JimWideValue(objPtr));
-    objPtr->bytes = Jim_Alloc(len + 1);
-    memcpy(objPtr->bytes, buf, len + 1);
-    objPtr->length = len;
+    if (wideValue == 0) {
+        buf[pos++] = '0';
+    }
+    else {
+        char tmp[JIM_INTEGER_SPACE];
+        int num = 0;
+        int i;
+
+        if (wideValue < 0) {
+            buf[pos++] = '-';
+            i = wideValue % 10;
+            /* C89 is implementation defined as to whether (-106 % 10) is -6 or 4,
+             * whereas C99 is always -6
+             * coverity[dead_error_line]
+             */
+            tmp[num++] = (i > 0) ? (10 - i) : -i;
+            wideValue /= -10;
+        }
+
+        while (wideValue) {
+            tmp[num++] = wideValue % 10;
+            wideValue /= 10;
+        }
+
+        for (i = 0; i < num; i++) {
+            buf[pos++] = '0' + tmp[num - i - 1];
+        }
+    }
+    buf[pos] = 0;
+
+    JimSetStringBytes(objPtr, buf);
 }
 
-int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
+static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags)
 {
     jim_wide wideValue;
     const char *str;
@@ -5405,18 +5911,64 @@ static const Jim_ObjType doubleObjType = {
     JIM_TYPE_NONE,
 };
 
-void UpdateStringOfDouble(struct Jim_Obj *objPtr)
+#ifndef HAVE_ISNAN
+#undef isnan
+#define isnan(X) ((X) != (X))
+#endif
+#ifndef HAVE_ISINF
+#undef isinf
+#define isinf(X) (1.0 / (X) == 0.0)
+#endif
+
+static void UpdateStringOfDouble(struct Jim_Obj *objPtr)
 {
-    int len;
-    char buf[JIM_DOUBLE_SPACE + 1];
+    double value = objPtr->internalRep.doubleValue;
 
-    len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
-    objPtr->bytes = Jim_Alloc(len + 1);
-    memcpy(objPtr->bytes, buf, len + 1);
-    objPtr->length = len;
+    if (isnan(value)) {
+        JimSetStringBytes(objPtr, "NaN");
+        return;
+    }
+    if (isinf(value)) {
+        if (value < 0) {
+            JimSetStringBytes(objPtr, "-Inf");
+        }
+        else {
+            JimSetStringBytes(objPtr, "Inf");
+        }
+        return;
+    }
+    {
+        char buf[JIM_DOUBLE_SPACE + 1];
+        int i;
+        int len = sprintf(buf, "%.12g", value);
+
+        /* Add a final ".0" if necessary */
+        for (i = 0; i < len; i++) {
+            if (buf[i] == '.' || buf[i] == 'e') {
+#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
+                /* If 'buf' ends in e-0nn or e+0nn, remove
+                 * the 0 after the + or - and reduce the length by 1
+                 */
+                char *e = strchr(buf, 'e');
+                if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
+                    /* Move it up */
+                    e += 2;
+                    memmove(e, e + 1, len - (e - buf));
+                }
+#endif
+                break;
+            }
+        }
+        if (buf[i] == '\0') {
+            buf[i++] = '.';
+            buf[i++] = '0';
+            buf[i] = '\0';
+        }
+        JimSetStringBytes(objPtr, buf);
+    }
 }
 
-int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 {
     double doubleValue;
     jim_wide wideValue;
@@ -5495,6 +6047,7 @@ Jim_Obj *Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue)
 /* -----------------------------------------------------------------------------
  * List object
  * ---------------------------------------------------------------------------*/
+static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec);
 static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr);
 static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
 static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
@@ -5547,15 +6100,13 @@ void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
 #define JIM_ELESTR_SIMPLE 0
 #define JIM_ELESTR_BRACE 1
 #define JIM_ELESTR_QUOTE 2
-static int ListElementQuotingType(const char *s, int len)
+static unsigned char ListElementQuotingType(const char *s, int len)
 {
     int i, level, blevel, trySimple = 1;
 
     /* Try with the SIMPLE case */
     if (len == 0)
         return JIM_ELESTR_BRACE;
-    if (s[0] == '#')
-        return JIM_ELESTR_BRACE;
     if (s[0] == '"' || s[0] == '{') {
         trySimple = 0;
         goto testbrace;
@@ -5642,14 +6193,16 @@ static int ListElementQuotingType(const char *s, int len)
     return JIM_ELESTR_QUOTE;
 }
 
-/* Returns the malloc-ed representation of a string
- * using backslash to quote special chars. */
-static char *BackslashQuoteString(const char *s, int len, int *qlenPtr)
+/* Backslashes-escapes the null-terminated string 's' into the buffer at 'q'
+ * The buffer must be at least strlen(s) * 2 + 1 bytes long for the worst-case
+ * scenario.
+ * Returns the length of the result.
+ */
+static int BackslashQuoteString(const char *s, int len, char *q)
 {
-    char *q = Jim_Alloc(len * 2 + 1), *p;
+    char *p = q;
 
-    p = q;
-    while (*s) {
+    while (len--) {
         switch (*s) {
             case ' ':
             case '$':
@@ -5694,30 +6247,40 @@ static char *BackslashQuoteString(const char *s, int len, int *qlenPtr)
         }
     }
     *p = '\0';
-    *qlenPtr = p - q;
-    return q;
+
+    return p - q;
 }
 
-static void UpdateStringOfList(struct Jim_Obj *objPtr)
+static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
 {
+    #define STATIC_QUOTING_LEN 32
     int i, bufLen, realLength;
     const char *strRep;
     char *p;
-    int *quotingType;
-    Jim_Obj **ele = objPtr->internalRep.listValue.ele;
+    unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
 
-    /* (Over) Estimate the space needed. */
-    quotingType = Jim_Alloc(sizeof(int) * objPtr->internalRep.listValue.len + 1);
+    /* Estimate the space needed. */
+    if (objc > STATIC_QUOTING_LEN) {
+        quotingType = Jim_Alloc(objc);
+    }
+    else {
+        quotingType = staticQuoting;
+    }
     bufLen = 0;
-    for (i = 0; i < objPtr->internalRep.listValue.len; i++) {
+    for (i = 0; i < objc; i++) {
         int len;
 
-        strRep = Jim_GetString(ele[i], &len);
+        strRep = Jim_GetString(objv[i], &len);
         quotingType[i] = ListElementQuotingType(strRep, len);
         switch (quotingType[i]) {
             case JIM_ELESTR_SIMPLE:
-                bufLen += len;
-                break;
+                if (i != 0 || strRep[0] != '#') {
+                    bufLen += len;
+                    break;
+                }
+                /* Special case '#' on first element needs braces */
+                quotingType[i] = JIM_ELESTR_BRACE;
+                /* fall through */
             case JIM_ELESTR_BRACE:
                 bufLen += len + 2;
                 break;
@@ -5732,11 +6295,10 @@ static void UpdateStringOfList(struct Jim_Obj *objPtr)
     /* Generate the string rep. */
     p = objPtr->bytes = Jim_Alloc(bufLen + 1);
     realLength = 0;
-    for (i = 0; i < objPtr->internalRep.listValue.len; i++) {
+    for (i = 0; i < objc; i++) {
         int len, qlen;
-        char *q;
 
-        strRep = Jim_GetString(ele[i], &len);
+        strRep = Jim_GetString(objv[i], &len);
 
         switch (quotingType[i]) {
             case JIM_ELESTR_SIMPLE:
@@ -5752,25 +6314,35 @@ static void UpdateStringOfList(struct Jim_Obj *objPtr)
                 realLength += len + 2;
                 break;
             case JIM_ELESTR_QUOTE:
-                q = BackslashQuoteString(strRep, len, &qlen);
-                memcpy(p, q, qlen);
-                Jim_Free(q);
+                if (i == 0 && strRep[0] == '#') {
+                    *p++ = '\\';
+                    realLength++;
+                }
+                qlen = BackslashQuoteString(strRep, len, p);
                 p += qlen;
                 realLength += qlen;
                 break;
         }
         /* Add a separating space */
-        if (i + 1 != objPtr->internalRep.listValue.len) {
+        if (i + 1 != objc) {
             *p++ = ' ';
             realLength++;
         }
     }
     *p = '\0';                  /* nul term. */
     objPtr->length = realLength;
-    Jim_Free(quotingType);
+
+    if (quotingType != staticQuoting) {
+        Jim_Free(quotingType);
+    }
+}
+
+static void UpdateStringOfList(struct Jim_Obj *objPtr)
+{
+    JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
 }
 
-int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
+static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 {
     struct JimParserCtx parser;
     const char *str;
@@ -5778,6 +6350,34 @@ int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
     Jim_Obj *fileNameObj;
     int linenr;
 
+    if (objPtr->typePtr == &listObjType) {
+        return JIM_OK;
+    }
+
+    /* Optimise dict -> list for object with no string rep. Note that this may only save a little time, but
+     * it also preserves any source location of the dict elements
+     * which can be very useful
+     */
+    if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) {
+        Jim_Obj **listObjPtrPtr;
+        int len;
+        int i;
+
+        listObjPtrPtr = JimDictPairs(objPtr, &len);
+        for (i = 0; i < len; i++) {
+            Jim_IncrRefCount(listObjPtrPtr[i]);
+        }
+
+        /* Now just switch the internal rep */
+        Jim_FreeIntRep(interp, objPtr);
+        objPtr->typePtr = &listObjType;
+        objPtr->internalRep.listValue.len = len;
+        objPtr->internalRep.listValue.maxLen = len;
+        objPtr->internalRep.listValue.ele = listObjPtrPtr;
+
+        return JIM_OK;
+    }
+
     /* Try to preserve information about filename / line number */
     if (objPtr->typePtr == &sourceObjType) {
         fileNameObj = objPtr->internalRep.sourceValue.fileNameObj;
@@ -5801,16 +6401,18 @@ int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
     objPtr->internalRep.listValue.ele = NULL;
 
     /* Convert into a list */
-    JimParserInit(&parser, str, strLen, linenr);
-    while (!parser.eof) {
-        Jim_Obj *elementPtr;
+    if (strLen) {
+        JimParserInit(&parser, str, strLen, linenr);
+        while (!parser.eof) {
+            Jim_Obj *elementPtr;
 
-        JimParseList(&parser);
-        if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC)
-            continue;
-        elementPtr = JimParserGetTokenObj(interp, &parser);
-        JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline);
-        ListAppendElement(objPtr, elementPtr);
+            JimParseList(&parser);
+            if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC)
+                continue;
+            elementPtr = JimParserGetTokenObj(interp, &parser);
+            JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline);
+            ListAppendElement(objPtr, elementPtr);
+        }
     }
     Jim_DecrRefCount(interp, fileNameObj);
     return JIM_OK;
@@ -5819,7 +6421,6 @@ int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
 {
     Jim_Obj *objPtr;
-    int i;
 
     objPtr = Jim_NewObj(interp);
     objPtr->typePtr = &listObjType;
@@ -5827,9 +6428,11 @@ Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
     objPtr->internalRep.listValue.ele = NULL;
     objPtr->internalRep.listValue.len = 0;
     objPtr->internalRep.listValue.maxLen = 0;
-    for (i = 0; i < len; i++) {
-        ListAppendElement(objPtr, elements[i]);
+
+    if (len) {
+        ListInsertElements(objPtr, 0, len, elements);
     }
+
     return objPtr;
 }
 
@@ -5867,11 +6470,13 @@ struct lsort_info {
         JIM_LSORT_ASCII,
         JIM_LSORT_NOCASE,
         JIM_LSORT_INTEGER,
+        JIM_LSORT_REAL,
         JIM_LSORT_COMMAND
     } type;
     int order;
     int index;
     int indexed;
+    int unique;
     int (*subfn)(Jim_Obj **, Jim_Obj **);
 };
 
@@ -5911,6 +6516,23 @@ static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
     return JimSign(lhs - rhs) * sort_info->order;
 }
 
+static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
+{
+    double lhs = 0, rhs = 0;
+
+    if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK ||
+        Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) {
+        longjmp(sort_info->jmpbuf, JIM_ERR);
+    }
+    if (lhs == rhs) {
+        return 0;
+    }
+    if (lhs > rhs) {
+        return sort_info->order;
+    }
+    return -sort_info->order;
+}
+
 static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
 {
     Jim_Obj *compare_script;
@@ -5932,7 +6554,36 @@ static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj)
     return JimSign(ret) * sort_info->order;
 }
 
-/* Sort a list *in place*. MUST be called with non-shared objects. */
+/* Remove duplicate elements from the (sorted) list in-place, according to the
+ * comparison function, comp.
+ *
+ * Note that the last unique value is kept, not the first
+ */
+static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs))
+{
+    int src;
+    int dst = 0;
+    Jim_Obj **ele = listObjPtr->internalRep.listValue.ele;
+
+    for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) {
+        if (comp(&ele[dst], &ele[src]) == 0) {
+            /* Match, so replace the dest with the current source */
+            Jim_DecrRefCount(sort_info->interp, ele[dst]);
+        }
+        else {
+            /* No match, so keep the current source and move to the next destination */
+            dst++;
+        }
+        ele[dst] = ele[src];
+    }
+    /* At end of list, keep the final element */
+    ele[++dst] = ele[src];
+
+    /* Set the new length */
+    listObjPtr->internalRep.listValue.len = dst;
+}
+
+/* Sort a list *in place*. MUST be called with a non-shared list. */
 static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info)
 {
     struct lsort_info *prev_info;
@@ -5943,9 +6594,8 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
     int len;
     int rc;
 
-    JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object"));
-    if (!Jim_IsList(listObjPtr))
-        SetListFromAny(interp, listObjPtr);
+    JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object"));
+    SetListFromAny(interp, listObjPtr);
 
     /* Allow lsort to be called reentrantly */
     prev_info = sort_info;
@@ -5963,6 +6613,9 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
         case JIM_LSORT_INTEGER:
             fn = ListSortInteger;
             break;
+        case JIM_LSORT_REAL:
+            fn = ListSortReal;
+            break;
         case JIM_LSORT_COMMAND:
             fn = ListSortCommand;
             break;
@@ -5979,8 +6632,13 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
 
     if ((rc = setjmp(info->jmpbuf)) == 0) {
         qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn);
+
+        if (info->unique && len > 1) {
+            ListRemoveDuplicates(listObjPtr, fn);
+        }
+
+        Jim_InvalidateStringRep(listObjPtr);
     }
-    Jim_InvalidateStringRep(listObjPtr);
     sort_info = prev_info;
 
     return rc;
@@ -5988,11 +6646,14 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
 
 /* This is the low-level function to insert elements into a list.
  * The higher-level Jim_ListInsertElements() performs shared object
- * check and invalidate the string repr. This version is used
+ * check and invalidates the string repr. This version is used
  * in the internals of the List Object and is not exported.
  *
  * NOTE: this function can be called only against objects
- * with internal type of List. */
+ * with internal type of List.
+ *
+ * An insertion point (idx) of -1 means end-of-list.
+ */
 static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec)
 {
     int currentLen = listPtr->internalRep.listValue.len;
@@ -6001,11 +6662,21 @@ static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *co
     Jim_Obj **point;
 
     if (requiredLen > listPtr->internalRep.listValue.maxLen) {
-        int maxLen = requiredLen * 2;
+        if (requiredLen < 2) {
+            /* Don't do allocations of under 4 pointers. */
+            requiredLen = 4;
+        }
+        else {
+            requiredLen *= 2;
+        }
+
+        listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
+            sizeof(Jim_Obj *) * requiredLen);
 
-        listPtr->internalRep.listValue.ele =
-            Jim_Realloc(listPtr->internalRep.listValue.ele, sizeof(Jim_Obj *) * maxLen);
-        listPtr->internalRep.listValue.maxLen = maxLen;
+        listPtr->internalRep.listValue.maxLen = requiredLen;
+    }
+    if (idx < 0) {
+        idx = currentLen;
     }
     point = listPtr->internalRep.listValue.ele + idx;
     memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *));
@@ -6020,25 +6691,23 @@ static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *co
  */
 static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr)
 {
-    ListInsertElements(listPtr, listPtr->internalRep.listValue.len, 1, &objPtr);
+    ListInsertElements(listPtr, -1, 1, &objPtr);
 }
 
-
 /* Appends every element of appendListPtr into listPtr.
  * Both have to be of the list type.
  * Convenience call to ListInsertElements()
  */
 static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr)
 {
-    ListInsertElements(listPtr, listPtr->internalRep.listValue.len,
+    ListInsertElements(listPtr, -1,
         appendListPtr->internalRep.listValue.len, appendListPtr->internalRep.listValue.ele);
 }
 
 void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr)
 {
     JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendElement called with shared object"));
-    if (!Jim_IsList(listPtr))
-        SetListFromAny(interp, listPtr);
+    SetListFromAny(interp, listPtr);
     Jim_InvalidateStringRep(listPtr);
     ListAppendElement(listPtr, objPtr);
 }
@@ -6046,16 +6715,15 @@ void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr
 void Jim_ListAppendList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr)
 {
     JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendList called with shared object"));
-    if (!Jim_IsList(listPtr))
-        SetListFromAny(interp, listPtr);
+    SetListFromAny(interp, listPtr);
+    SetListFromAny(interp, appendListPtr);
     Jim_InvalidateStringRep(listPtr);
     ListAppendList(listPtr, appendListPtr);
 }
 
 int Jim_ListLength(Jim_Interp *interp, Jim_Obj *objPtr)
 {
-    if (!Jim_IsList(objPtr))
-        SetListFromAny(interp, objPtr);
+    SetListFromAny(interp, objPtr);
     return objPtr->internalRep.listValue.len;
 }
 
@@ -6063,8 +6731,7 @@ void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
     int objc, Jim_Obj *const *objVec)
 {
     JimPanic((Jim_IsShared(listPtr), "Jim_ListInsertElement called with shared object"));
-    if (!Jim_IsList(listPtr))
-        SetListFromAny(interp, listPtr);
+    SetListFromAny(interp, listPtr);
     if (idx >= 0 && idx > listPtr->internalRep.listValue.len)
         idx = listPtr->internalRep.listValue.len;
     else if (idx < 0)
@@ -6073,29 +6740,34 @@ void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
     ListInsertElements(listPtr, idx, objc, objVec);
 }
 
-int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPtrPtr, int flags)
+Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx)
 {
-    if (!Jim_IsList(listPtr))
-        SetListFromAny(interp, listPtr);
+    SetListFromAny(interp, listPtr);
     if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) ||
         (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) {
+        return NULL;
+    }
+    if (idx < 0)
+        idx = listPtr->internalRep.listValue.len + idx;
+    return listPtr->internalRep.listValue.ele[idx];
+}
+
+int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPtrPtr, int flags)
+{
+    *objPtrPtr = Jim_ListGetIndex(interp, listPtr, idx);
+    if (*objPtrPtr == NULL) {
         if (flags & JIM_ERRMSG) {
             Jim_SetResultString(interp, "list index out of range", -1);
         }
-        *objPtrPtr = NULL;
         return JIM_ERR;
     }
-    if (idx < 0)
-        idx = listPtr->internalRep.listValue.len + idx;
-    *objPtrPtr = listPtr->internalRep.listValue.ele[idx];
     return JIM_OK;
 }
 
 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
     Jim_Obj *newObjPtr, int flags)
 {
-    if (!Jim_IsList(listPtr))
-        SetListFromAny(interp, listPtr);
+    SetListFromAny(interp, listPtr);
     if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) ||
         (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) {
         if (flags & JIM_ERRMSG) {
@@ -6111,10 +6783,10 @@ static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx,
     return JIM_OK;
 }
 
-/* Modify the list stored into the variable named 'varNamePtr'
+/* Modify the list stored in the variable named 'varNamePtr'
  * setting the element specified by the 'indexc' indexes objects in 'indexv',
- * with the new element 'newObjptr'. */
-int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
+ * with the new element 'newObjptr'. (implements the [lset] command) */
+int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
     Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr)
 {
     Jim_Obj *varObjPtr, *objPtr, *listObjPtr;
@@ -6155,6 +6827,21 @@ int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr,
     return JIM_ERR;
 }
 
+Jim_Obj *Jim_ListJoin(Jim_Interp *interp, Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen)
+{
+    int i;
+    int listLen = Jim_ListLength(interp, listObjPtr);
+    Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp);
+
+    for (i = 0; i < listLen; ) {
+        Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i));
+        if (++i != listLen) {
+            Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
+        }
+    }
+    return resObjPtr;
+}
+
 Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
 {
     int i;
@@ -6170,7 +6857,7 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
         Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
 
         for (i = 0; i < objc; i++)
-            Jim_ListAppendList(interp, objPtr, objv[i]);
+            ListAppendList(objPtr, objv[i]);
         return objPtr;
     }
     else {
@@ -6180,8 +6867,7 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
 
         /* Compute the length */
         for (i = 0; i < objc; i++) {
-            Jim_GetString(objv[i], &objLen);
-            len += objLen;
+            len += Jim_Length(objv[i]);
         }
         if (objc)
             len += objc - 1;
@@ -6191,14 +6877,13 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
             const char *s = Jim_GetString(objv[i], &objLen);
 
             /* Remove leading space */
-            while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) {
+            while (objLen && isspace(UCHAR(*s))) {
                 s++;
                 objLen--;
                 len--;
             }
             /* And trailing space */
-            while (objLen && (s[objLen - 1] == ' ' ||
-                    s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) {
+            while (objLen && isspace(UCHAR(s[objLen - 1]))) {
                 /* Handle trailing backslash-space case */
                 if (objLen > 1 && s[objLen - 2] == '\\') {
                     break;
@@ -6208,13 +6893,14 @@ Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
             }
             memcpy(p, s, objLen);
             p += objLen;
-            if (objLen && i + 1 != objc) {
-                *p++ = ' ';
-            }
-            else if (i + 1 != objc) {
-                /* Drop the space calcuated for this
-                 * element that is instead null. */
-                len--;
+            if (i + 1 != objc) {
+                if (objLen)
+                    *p++ = ' ';
+                else {
+                    /* Drop the space calcuated for this
+                     * element that is instead null. */
+                    len--;
+                }
             }
         }
         *p = '\0';
@@ -6237,7 +6923,7 @@ Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstOb
     len = Jim_ListLength(interp, listObjPtr);   /* will convert into list */
     first = JimRelToAbsIndex(len, first);
     last = JimRelToAbsIndex(len, last);
-    JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
+    JimRelToAbsRange(len, &first, &last, &rangeLen);
     if (first == 0 && last == len) {
         return listObjPtr;
     }
@@ -6258,35 +6944,33 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
 
 static unsigned int JimObjectHTHashFunction(const void *key)
 {
-    const char *str;
-    Jim_Obj *objPtr = (Jim_Obj *)key;
     int len;
-
-    str = Jim_GetString(objPtr, &len);
-    return Jim_GenHashFunction((unsigned char *)str, len);
+    const char *str = Jim_GetString((Jim_Obj *)key, &len);
+    return Jim_GenHashFunction((const unsigned char *)str, len);
 }
 
 static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2)
 {
-    JIM_NOTUSED(privdata);
-
     return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2);
 }
 
-static void JimObjectHTKeyValDestructor(void *interp, void *val)
+static void *JimObjectHTKeyValDup(void *privdata, const void *val)
 {
-    Jim_Obj *objPtr = val;
+    Jim_IncrRefCount((Jim_Obj *)val);
+    return (void *)val;
+}
 
-    Jim_DecrRefCount(interp, objPtr);
+static void JimObjectHTKeyValDestructor(void *interp, void *val)
+{
+    Jim_DecrRefCount(interp, (Jim_Obj *)val);
 }
 
 static const Jim_HashTableType JimDictHashTableType = {
     JimObjectHTHashFunction,    /* hash function */
-    NULL,                       /* key dup */
-    NULL,                       /* val dup */
+    JimObjectHTKeyValDup,       /* key dup */
+    JimObjectHTKeyValDup,       /* val dup */
     JimObjectHTKeyCompare,      /* key compare */
-    (void (*)(void *, const void *))    /* ATTENTION: const cast */
-        JimObjectHTKeyValDestructor,    /* key destructor */
+    JimObjectHTKeyValDestructor,    /* key destructor */
     JimObjectHTKeyValDestructor /* val destructor */
 };
 
@@ -6313,7 +6997,7 @@ void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
 void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
 {
     Jim_HashTable *ht, *dupHt;
-    Jim_HashTableIterator *htiter;
+    Jim_HashTableIterator htiter;
     Jim_HashEntry *he;
 
     /* Create a new hash table */
@@ -6323,105 +7007,46 @@ void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
     if (ht->size != 0)
         Jim_ExpandHashTable(dupHt, ht->size);
     /* Copy every element from the source to the dup hash table */
-    htiter = Jim_GetHashTableIterator(ht);
-    while ((he = Jim_NextHashEntry(htiter)) != NULL) {
-        const Jim_Obj *keyObjPtr = he->key;
-        Jim_Obj *valObjPtr = he->u.val;
-
-        Jim_IncrRefCount((Jim_Obj *)keyObjPtr); /* ATTENTION: const cast */
-        Jim_IncrRefCount(valObjPtr);
-        Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
+    JimInitHashTableIterator(ht, &htiter);
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        Jim_AddHashEntry(dupHt, he->key, he->u.val);
     }
-    Jim_FreeHashTableIterator(htiter);
 
     dupPtr->internalRep.ptr = dupHt;
     dupPtr->typePtr = &dictObjType;
 }
 
-void UpdateStringOfDict(struct Jim_Obj *objPtr)
+static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
 {
-    int i, bufLen, realLength;
-    const char *strRep;
-    char *p;
-    int *quotingType, objc;
     Jim_HashTable *ht;
-    Jim_HashTableIterator *htiter;
+    Jim_HashTableIterator htiter;
     Jim_HashEntry *he;
     Jim_Obj **objv;
+    int i;
 
-    /* Trun the hash table into a flat vector of Jim_Objects. */
-    ht = objPtr->internalRep.ptr;
-    objc = ht->used * 2;
-    objv = Jim_Alloc(objc * sizeof(Jim_Obj *));
-    htiter = Jim_GetHashTableIterator(ht);
-    i = 0;
-    while ((he = Jim_NextHashEntry(htiter)) != NULL) {
-        objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */
-        objv[i++] = he->u.val;
-    }
-    Jim_FreeHashTableIterator(htiter);
-    /* (Over) Estimate the space needed. */
-    quotingType = Jim_Alloc(sizeof(int) * objc);
-    bufLen = 0;
-    for (i = 0; i < objc; i++) {
-        int len;
+    ht = dictPtr->internalRep.ptr;
 
-        strRep = Jim_GetString(objv[i], &len);
-        quotingType[i] = ListElementQuotingType(strRep, len);
-        switch (quotingType[i]) {
-            case JIM_ELESTR_SIMPLE:
-                bufLen += len;
-                break;
-            case JIM_ELESTR_BRACE:
-                bufLen += len + 2;
-                break;
-            case JIM_ELESTR_QUOTE:
-                bufLen += len * 2;
-                break;
-        }
-        bufLen++;               /* elements separator. */
+    /* Turn the hash table into a flat vector of Jim_Objects. */
+    objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
+    JimInitHashTableIterator(ht, &htiter);
+    i = 0;
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        objv[i++] = Jim_GetHashEntryKey(he);
+        objv[i++] = Jim_GetHashEntryVal(he);
     }
-    bufLen++;
+    *len = i;
+    return objv;
+}
 
-    /* Generate the string rep. */
-    p = objPtr->bytes = Jim_Alloc(bufLen + 1);
-    realLength = 0;
-    for (i = 0; i < objc; i++) {
-        int len, qlen;
-        char *q;
+static void UpdateStringOfDict(struct Jim_Obj *objPtr)
+{
+    /* Turn the hash table into a flat vector of Jim_Objects. */
+    int len;
+    Jim_Obj **objv = JimDictPairs(objPtr, &len);
 
-        strRep = Jim_GetString(objv[i], &len);
+    /* And now generate the string rep as a list */
+    JimMakeListStringRep(objPtr, objv, len);
 
-        switch (quotingType[i]) {
-            case JIM_ELESTR_SIMPLE:
-                memcpy(p, strRep, len);
-                p += len;
-                realLength += len;
-                break;
-            case JIM_ELESTR_BRACE:
-                *p++ = '{';
-                memcpy(p, strRep, len);
-                p += len;
-                *p++ = '}';
-                realLength += len + 2;
-                break;
-            case JIM_ELESTR_QUOTE:
-                q = BackslashQuoteString(strRep, len, &qlen);
-                memcpy(p, q, qlen);
-                Jim_Free(q);
-                p += qlen;
-                realLength += qlen;
-                break;
-        }
-        /* Add a separating space */
-        if (i + 1 != objc) {
-            *p++ = ' ';
-            realLength++;
-        }
-    }
-    *p = '\0';                  /* nul term. */
-    objPtr->length = realLength;
-    Jim_Free(quotingType);
     Jim_Free(objv);
 }
 
@@ -6429,20 +7054,25 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 {
     int listlen;
 
-    /* Get the string representation. Do this first so we don't
-     * change order in case of fast conversion to dict.
-     */
-    Jim_String(objPtr);
+    if (objPtr->typePtr == &dictObjType) {
+        return JIM_OK;
+    }
+
+    if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) {
+        /* A shared list, so get the string representation now to avoid
+         * changing the order in case of fast conversion to dict.
+         */
+        Jim_String(objPtr);
+    }
 
     /* For simplicity, convert a non-list object to a list and then to a dict */
     listlen = Jim_ListLength(interp, objPtr);
     if (listlen % 2) {
-        Jim_SetResultString(interp,
-            "invalid dictionary value: must be a list with an even number of elements", -1);
+        Jim_SetResultString(interp, "missing value to go with key", -1);
         return JIM_ERR;
     }
     else {
-        /* Now it is easy to convert to a dict from a list, and it can't fail */
+        /* Converting from a list to a dict can't fail */
         Jim_HashTable *ht;
         int i;
 
@@ -6450,24 +7080,10 @@ static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
         Jim_InitHashTable(ht, &JimDictHashTableType, interp);
 
         for (i = 0; i < listlen; i += 2) {
-            Jim_Obj *keyObjPtr;
-            Jim_Obj *valObjPtr;
-
-            Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE);
-            Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE);
+            Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i);
+            Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1);
 
-            Jim_IncrRefCount(keyObjPtr);
-            Jim_IncrRefCount(valObjPtr);
-
-            if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) {
-                Jim_HashEntry *he;
-
-                he = Jim_FindHashEntry(ht, keyObjPtr);
-                Jim_DecrRefCount(interp, keyObjPtr);
-                /* ATTENTION: const cast */
-                Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
-                he->u.val = valObjPtr;
-            }
+            Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr);
         }
 
         Jim_FreeIntRep(interp, objPtr);
@@ -6494,16 +7110,7 @@ static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
     if (valueObjPtr == NULL) {  /* unset */
         return Jim_DeleteHashEntry(ht, keyObjPtr);
     }
-    Jim_IncrRefCount(keyObjPtr);
-    Jim_IncrRefCount(valueObjPtr);
-    if (Jim_AddHashEntry(ht, keyObjPtr, valueObjPtr) != JIM_OK) {
-        Jim_HashEntry *he = Jim_FindHashEntry(ht, keyObjPtr);
-
-        Jim_DecrRefCount(interp, keyObjPtr);
-        /* ATTENTION: const cast */
-        Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val);
-        he->u.val = valueObjPtr;
-    }
+    Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr);
     return JIM_OK;
 }
 
@@ -6512,16 +7119,12 @@ static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
 int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
     Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr)
 {
-    int retcode;
-
     JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object"));
-    if (objPtr->typePtr != &dictObjType) {
-        if (SetDictFromAny(interp, objPtr) != JIM_OK)
-            return JIM_ERR;
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return JIM_ERR;
     }
-    retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
     Jim_InvalidateStringRep(objPtr);
-    return retcode;
+    return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr);
 }
 
 Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
@@ -6542,7 +7145,9 @@ Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len)
 }
 
 /* Return the value associated to the specified dict key
- * Note: Returns JIM_OK if OK, JIM_ERR if entry not found or -1 if can't create dict value
+ * Returns JIM_OK if OK, JIM_ERR if entry not found or -1 if can't create dict value
+ *
+ * Sets *objPtrPtr to non-NULL only upon success.
  */
 int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
     Jim_Obj **objPtrPtr, int flags)
@@ -6550,14 +7155,13 @@ int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
     Jim_HashEntry *he;
     Jim_HashTable *ht;
 
-    if (dictPtr->typePtr != &dictObjType) {
-        if (SetDictFromAny(interp, dictPtr) != JIM_OK)
-            return -1;
+    if (SetDictFromAny(interp, dictPtr) != JIM_OK) {
+        return -1;
     }
     ht = dictPtr->internalRep.ptr;
     if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) {
         if (flags & JIM_ERRMSG) {
-            Jim_SetResultFormatted(interp, "key \"%#s\" not found in dictionary", keyPtr);
+            Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr);
         }
         return JIM_ERR;
     }
@@ -6568,29 +7172,11 @@ int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr,
 /* Return an allocated array of key/value pairs for the dictionary. Stores the length in *len */
 int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len)
 {
-    Jim_HashTable *ht;
-    Jim_HashTableIterator *htiter;
-    Jim_HashEntry *he;
-    Jim_Obj **objv;
-    int i;
-
-    if (dictPtr->typePtr != &dictObjType) {
-        if (SetDictFromAny(interp, dictPtr) != JIM_OK)
-            return JIM_ERR;
+    if (SetDictFromAny(interp, dictPtr) != JIM_OK) {
+        return JIM_ERR;
     }
-    ht = dictPtr->internalRep.ptr;
+    *objPtrPtr = JimDictPairs(dictPtr, len);
 
-    /* Turn the hash table into a flat vector of Jim_Objects. */
-    objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
-    htiter = Jim_GetHashTableIterator(ht);
-    i = 0;
-    while ((he = Jim_NextHashEntry(htiter)) != NULL) {
-        objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */
-        objv[i++] = he->u.val;
-    }
-    *len = i;
-    Jim_FreeHashTableIterator(htiter);
-    *objPtrPtr = objv;
     return JIM_OK;
 }
 
@@ -6609,9 +7195,10 @@ int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr,
     for (i = 0; i < keyc; i++) {
         Jim_Obj *objPtr;
 
-        if (Jim_DictKey(interp, dictPtr, keyv[i], &objPtr, flags)
-            != JIM_OK)
-            return JIM_ERR;
+        int rc = Jim_DictKey(interp, dictPtr, keyv[i], &objPtr, flags);
+        if (rc != JIM_OK) {
+            return rc;
+        }
         dictPtr = objPtr;
     }
     *objPtrPtr = dictPtr;
@@ -6634,10 +7221,10 @@ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
     Jim_Obj *varObjPtr, *objPtr, *dictObjPtr;
     int shared, i;
 
-    varObjPtr = objPtr =
-        Jim_GetVariable(interp, varNamePtr, newObjPtr == NULL ? JIM_ERRMSG : JIM_NONE);
+    varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags);
     if (objPtr == NULL) {
-        if (newObjPtr == NULL)  /* Cannot remove a key from non existing var */ {
+        if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) {
+            /* Cannot remove a key from non existing var */
             return JIM_ERR;
         }
         varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
@@ -6648,15 +7235,24 @@ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
     }
     if ((shared = Jim_IsShared(objPtr)))
         varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr);
-    for (i = 0; i < keyc - 1; i++) {
+    for (i = 0; i < keyc; i++) {
         dictObjPtr = objPtr;
 
         /* Check if it's a valid dictionary */
-        if (dictObjPtr->typePtr != &dictObjType) {
-            if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
-                goto err;
+        if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) {
+            goto err;
+        }
+
+        if (i == keyc - 1) {
+            /* Last key: Note that error on unset with missing last key is OK */
+            if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
+                if (newObjPtr || (flags & JIM_MUSTEXIST)) {
+                    goto err;
+                }
             }
+            break;
         }
+
         /* Check if the given key exists. */
         Jim_InvalidateStringRep(dictObjPtr);
         if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr,
@@ -6681,12 +7277,7 @@ int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr,
             DictAddElement(interp, dictObjPtr, keyv[i], objPtr);
         }
     }
-    /* Note error on unset with missing last key is OK */
-    if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) {
-        if (newObjPtr || (flags & JIM_ERRMSG)) {
-            goto err;
-        }
-    }
+    /* XXX: Is this necessary? */
     Jim_InvalidateStringRep(objPtr);
     Jim_InvalidateStringRep(varObjPtr);
     if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
@@ -6715,24 +7306,25 @@ static const Jim_ObjType indexObjType = {
     JIM_TYPE_NONE,
 };
 
-void UpdateStringOfIndex(struct Jim_Obj *objPtr)
+static void UpdateStringOfIndex(struct Jim_Obj *objPtr)
 {
-    int len;
-    char buf[JIM_INTEGER_SPACE + 1];
-
-    if (objPtr->internalRep.indexValue >= 0)
-        len = sprintf(buf, "%d", objPtr->internalRep.indexValue);
-    else if (objPtr->internalRep.indexValue == -1)
-        len = sprintf(buf, "end");
+    if (objPtr->internalRep.intValue == -1) {
+        JimSetStringBytes(objPtr, "end");
+    }
     else {
-        len = sprintf(buf, "end%d", objPtr->internalRep.indexValue + 1);
+        char buf[JIM_INTEGER_SPACE + 1];
+        if (objPtr->internalRep.intValue >= 0) {
+            sprintf(buf, "%d", objPtr->internalRep.intValue);
+        }
+        else {
+            /* Must be <= -2 */
+            sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
+        }
+        JimSetStringBytes(objPtr, buf);
     }
-    objPtr->bytes = Jim_Alloc(len + 1);
-    memcpy(objPtr->bytes, buf, len + 1);
-    objPtr->length = len;
 }
 
-int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 {
     int idx, end = 0;
     const char *str;
@@ -6748,7 +7340,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
         idx = 0;
     }
     else {
-        idx = strtol(str, &endptr, 10);
+        idx = jim_strtol(str, &endptr);
 
         if (endptr == str) {
             goto badindex;
@@ -6760,7 +7352,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
     if (*str == '+' || *str == '-') {
         int sign = (*str == '+' ? 1 : -1);
 
-        idx += sign * strtol(++str, &endptr, 10);
+        idx += sign * jim_strtol(++str, &endptr);
         if (str == endptr || *endptr) {
             goto badindex;
         }
@@ -6789,7 +7381,7 @@ int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
     /* Free the old internal repr and set the new one. */
     Jim_FreeIntRep(interp, objPtr);
     objPtr->typePtr = &indexObjType;
-    objPtr->internalRep.indexValue = idx;
+    objPtr->internalRep.intValue = idx;
     return JIM_OK;
 
   badindex:
@@ -6804,14 +7396,17 @@ int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
     if (objPtr->typePtr == &intObjType) {
         jim_wide val = JimWideValue(objPtr);
 
-        if (!(val < LONG_MIN) && !(val > LONG_MAX)) {
-            *indexPtr = (val < 0) ? -INT_MAX : (long)val;;
-            return JIM_OK;
-        }
+        if (val < 0)
+            *indexPtr = -INT_MAX;
+        else if (val > INT_MAX)
+            *indexPtr = INT_MAX;
+        else
+            *indexPtr = (int)val;
+        return JIM_OK;
     }
     if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR)
         return JIM_ERR;
-    *indexPtr = objPtr->internalRep.indexValue;
+    *indexPtr = objPtr->internalRep.intValue;
     return JIM_OK;
 }
 
@@ -6821,21 +7416,19 @@ int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr)
 
 /* NOTE: These must be kept in the same order as JIM_OK, JIM_ERR, ... */
 static const char * const jimReturnCodes[] = {
-    [JIM_OK] = "ok",
-    [JIM_ERR] = "error",
-    [JIM_RETURN] = "return",
-    [JIM_BREAK] = "break",
-    [JIM_CONTINUE] = "continue",
-    [JIM_SIGNAL] = "signal",
-    [JIM_EXIT] = "exit",
-    [JIM_EVAL] = "eval",
+    "ok",
+    "error",
+    "return",
+    "break",
+    "continue",
+    "signal",
+    "exit",
+    "eval",
     NULL
 };
 
 #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes))
 
-static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
-
 static const Jim_ObjType returnCodeObjType = {
     "return-code",
     NULL,
@@ -6857,7 +7450,7 @@ const char *Jim_ReturnCode(int code)
     }
 }
 
-int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
+static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
 {
     int returnCode;
     jim_wide wideValue;
@@ -6872,7 +7465,7 @@ int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
     /* Free the old internal repr and set the new one. */
     Jim_FreeIntRep(interp, objPtr);
     objPtr->typePtr = &returnCodeObjType;
-    objPtr->internalRep.returnCode = returnCode;
+    objPtr->internalRep.intValue = returnCode;
     return JIM_OK;
 }
 
@@ -6880,7 +7473,7 @@ int Jim_GetReturnCode(Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr)
 {
     if (objPtr->typePtr != &returnCodeObjType && SetReturnCodeFromAny(interp, objPtr) == JIM_ERR)
         return JIM_ERR;
-    *intPtr = objPtr->internalRep.returnCode;
+    *intPtr = objPtr->internalRep.intValue;
     return JIM_OK;
 }
 
@@ -6898,7 +7491,7 @@ enum
 {
     /* Continues on from the JIM_TT_ space */
     /* Operations */
-    JIM_EXPROP_MUL = JIM_TT_EXPR_OP,    /* 15 */
+    JIM_EXPROP_MUL = JIM_TT_EXPR_OP,             /* 20 */
     JIM_EXPROP_DIV,
     JIM_EXPROP_MOD,
     JIM_EXPROP_SUB,
@@ -6913,47 +7506,47 @@ enum
     JIM_EXPROP_GTE,
     JIM_EXPROP_NUMEQ,
     JIM_EXPROP_NUMNE,
-    JIM_EXPROP_BITAND,          /* 30 */
+    JIM_EXPROP_BITAND,          /* 35 */
     JIM_EXPROP_BITXOR,
     JIM_EXPROP_BITOR,
 
     /* Note must keep these together */
-    JIM_EXPROP_LOGICAND,        /* 33 */
+    JIM_EXPROP_LOGICAND,        /* 38 */
     JIM_EXPROP_LOGICAND_LEFT,
     JIM_EXPROP_LOGICAND_RIGHT,
 
     /* and these */
-    JIM_EXPROP_LOGICOR,         /* 36 */
+    JIM_EXPROP_LOGICOR,         /* 41 */
     JIM_EXPROP_LOGICOR_LEFT,
     JIM_EXPROP_LOGICOR_RIGHT,
 
     /* and these */
     /* Ternary operators */
-    JIM_EXPROP_TERNARY,         /* 39 */
+    JIM_EXPROP_TERNARY,         /* 44 */
     JIM_EXPROP_TERNARY_LEFT,
     JIM_EXPROP_TERNARY_RIGHT,
 
     /* and these */
-    JIM_EXPROP_COLON,           /* 42 */
+    JIM_EXPROP_COLON,           /* 47 */
     JIM_EXPROP_COLON_LEFT,
     JIM_EXPROP_COLON_RIGHT,
 
-    JIM_EXPROP_POW,             /* 45 */
+    JIM_EXPROP_POW,             /* 50 */
 
 /* Binary operators (strings) */
-    JIM_EXPROP_STREQ,
+    JIM_EXPROP_STREQ,           /* 51 */
     JIM_EXPROP_STRNE,
     JIM_EXPROP_STRIN,
     JIM_EXPROP_STRNI,
 
 /* Unary operators (numbers) */
-    JIM_EXPROP_NOT,
+    JIM_EXPROP_NOT,             /* 55 */
     JIM_EXPROP_BITNOT,
     JIM_EXPROP_UNARYMINUS,
     JIM_EXPROP_UNARYPLUS,
 
     /* Functions */
-    JIM_EXPROP_FUNC_FIRST,
+    JIM_EXPROP_FUNC_FIRST,      /* 59 */
     JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST,
     JIM_EXPROP_FUNC_ABS,
     JIM_EXPROP_FUNC_DOUBLE,
@@ -6962,7 +7555,7 @@ enum
     JIM_EXPROP_FUNC_SRAND,
 
     /* math functions from libm */
-    JIM_EXPROP_FUNC_SIN,
+    JIM_EXPROP_FUNC_SIN,        /* 64 */
     JIM_EXPROP_FUNC_COS,
     JIM_EXPROP_FUNC_TAN,
     JIM_EXPROP_FUNC_ASIN,
@@ -6992,10 +7585,11 @@ struct JimExprState
 typedef struct Jim_ExprOperator
 {
     const char *name;
-    int precedence;
-    int arity;
     int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
-    int lazy;
+    unsigned char precedence;
+    unsigned char arity;
+    unsigned char lazy;
+    unsigned char namelen;
 } Jim_ExprOperator;
 
 static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
@@ -7011,20 +7605,17 @@ static Jim_Obj *ExprPop(struct JimExprState *e)
 
 static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
 {
-    int intresult = 0;
+    int intresult = 1;
     int rc = JIM_OK;
     Jim_Obj *A = ExprPop(e);
     double dA, dC = 0;
     jim_wide wA, wC = 0;
 
     if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) {
-        intresult = 1;
-
         switch (e->opcode) {
             case JIM_EXPROP_FUNC_INT:
-                wC = wA;
-                break;
             case JIM_EXPROP_FUNC_ROUND:
+            case JIM_EXPROP_UNARYPLUS:
                 wC = wA;
                 break;
             case JIM_EXPROP_FUNC_DOUBLE:
@@ -7037,9 +7628,6 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
             case JIM_EXPROP_UNARYMINUS:
                 wC = -wA;
                 break;
-            case JIM_EXPROP_UNARYPLUS:
-                wC = wA;
-                break;
             case JIM_EXPROP_NOT:
                 wC = !wA;
                 break;
@@ -7051,27 +7639,25 @@ static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e)
         switch (e->opcode) {
             case JIM_EXPROP_FUNC_INT:
                 wC = dA;
-                intresult = 1;
                 break;
             case JIM_EXPROP_FUNC_ROUND:
                 wC = dA < 0 ? (dA - 0.5) : (dA + 0.5);
-                intresult = 1;
                 break;
             case JIM_EXPROP_FUNC_DOUBLE:
+            case JIM_EXPROP_UNARYPLUS:
                 dC = dA;
+                intresult = 0;
                 break;
             case JIM_EXPROP_FUNC_ABS:
                 dC = dA >= 0 ? dA : -dA;
+                intresult = 0;
                 break;
             case JIM_EXPROP_UNARYMINUS:
                 dC = -dA;
-                break;
-            case JIM_EXPROP_UNARYPLUS:
-                dC = dA;
+                intresult = 0;
                 break;
             case JIM_EXPROP_NOT:
                 wC = !dA;
-                intresult = 1;
                 break;
             default:
                 abort();
@@ -7294,7 +7880,7 @@ static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e)
 /* A binary operation on two ints or two doubles (or two strings for some ops) */
 static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
 {
-    int intresult = 0;
+    int intresult = 1;
     int rc = JIM_OK;
     double dA, dB, dC = 0;
     jim_wide wA, wB, wC = 0;
@@ -7308,8 +7894,6 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
 
         /* Both are ints */
 
-        intresult = 1;
-
         switch (e->opcode) {
             case JIM_EXPROP_POW:
             case JIM_EXPROP_FUNC_POW:
@@ -7371,6 +7955,7 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
         }
     }
     else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) {
+        intresult = 0;
         switch (e->opcode) {
             case JIM_EXPROP_POW:
             case JIM_EXPROP_FUNC_POW:
@@ -7433,11 +8018,9 @@ static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e)
     else {
         /* Handle the string case */
 
-        /* REVISIT: Could optimise the eq/ne case by checking lengths */
+        /* XXX: Could optimise the eq/ne case by checking lengths */
         int i = Jim_StringCompareObj(interp, A, B, 0);
 
-        intresult = 1;
-
         switch (e->opcode) {
             case JIM_EXPROP_LT:
                 wC = i < 0;
@@ -7485,11 +8068,7 @@ static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valOb
 
     listlen = Jim_ListLength(interp, listObjPtr);
     for (i = 0; i < listlen; i++) {
-        Jim_Obj *objPtr;
-
-        Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE);
-
-        if (Jim_StringEqObj(objPtr, valObj)) {
+        if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) {
             return 1;
         }
     }
@@ -7505,19 +8084,12 @@ static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e)
 
     switch (e->opcode) {
         case JIM_EXPROP_STREQ:
-        case JIM_EXPROP_STRNE: {
-            int Alen, Blen;
-            const char *sA = Jim_GetString(A, &Alen);
-            const char *sB = Jim_GetString(B, &Blen);
-
-            if (e->opcode == JIM_EXPROP_STREQ) {
-                wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0);
-            }
-            else {
-                wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0);
+        case JIM_EXPROP_STRNE:
+            wC = Jim_StringEqObj(A, B);
+            if (e->opcode == JIM_EXPROP_STRNE) {
+                wC = !wC;
             }
             break;
-        }
         case JIM_EXPROP_STRIN:
             wC = JimSearchList(interp, B, A);
             break;
@@ -7693,87 +8265,100 @@ enum
     LAZY_RIGHT
 };
 
-/* name - precedence - arity - opcode */
+/* name - precedence - arity - opcode
+ *
+ * This array *must* be kept in sync with the JIM_EXPROP enum.
+ *
+ * The following macros pre-compute the string length at compile time.
+ */
+#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1}
+#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
+
 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
-    [JIM_EXPROP_FUNC_INT] = {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_DOUBLE] = {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_ABS] = {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_ROUND] = {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_RAND] = {"rand", 400, 0, JimExprOpNone, LAZY_NONE},
-    [JIM_EXPROP_FUNC_SRAND] = {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE},
+    OPRINIT("*", 110, 2, JimExprOpBin),
+    OPRINIT("/", 110, 2, JimExprOpBin),
+    OPRINIT("%", 110, 2, JimExprOpIntBin),
 
-#ifdef JIM_MATH_FUNCTIONS
-    [JIM_EXPROP_FUNC_SIN] = {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_COS] = {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_TAN] = {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_ASIN] = {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_ACOS] = {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_ATAN] = {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_SINH] = {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_COSH] = {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_TANH] = {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_CEIL] = {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_FLOOR] = {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_EXP] = {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_LOG] = {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_LOG10] = {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_SQRT] = {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
-    [JIM_EXPROP_FUNC_POW] = {"pow", 400, 2, JimExprOpBin, LAZY_NONE},
-#endif
+    OPRINIT("-", 100, 2, JimExprOpBin),
+    OPRINIT("+", 100, 2, JimExprOpBin),
+
+    OPRINIT("<<", 90, 2, JimExprOpIntBin),
+    OPRINIT(">>", 90, 2, JimExprOpIntBin),
+
+    OPRINIT("<<<", 90, 2, JimExprOpIntBin),
+    OPRINIT(">>>", 90, 2, JimExprOpIntBin),
+
+    OPRINIT("<", 80, 2, JimExprOpBin),
+    OPRINIT(">", 80, 2, JimExprOpBin),
+    OPRINIT("<=", 80, 2, JimExprOpBin),
+    OPRINIT(">=", 80, 2, JimExprOpBin),
+
+    OPRINIT("==", 70, 2, JimExprOpBin),
+    OPRINIT("!=", 70, 2, JimExprOpBin),
 
-    [JIM_EXPROP_NOT] = {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE},
-    [JIM_EXPROP_BITNOT] = {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE},
-    [JIM_EXPROP_UNARYMINUS] = {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
-    [JIM_EXPROP_UNARYPLUS] = {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
+    OPRINIT("&", 50, 2, JimExprOpIntBin),
+    OPRINIT("^", 49, 2, JimExprOpIntBin),
+    OPRINIT("|", 48, 2, JimExprOpIntBin),
 
-    [JIM_EXPROP_POW] = {"**", 250, 2, JimExprOpBin, LAZY_NONE},
+    OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP),
+    OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
+    OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
 
-    [JIM_EXPROP_MUL] = {"*", 200, 2, JimExprOpBin, LAZY_NONE},
-    [JIM_EXPROP_DIV] = {"/", 200, 2, JimExprOpBin, LAZY_NONE},
-    [JIM_EXPROP_MOD] = {"%", 200, 2, JimExprOpIntBin, LAZY_NONE},
+    OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP),
+    OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
+    OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
 
-    [JIM_EXPROP_SUB] = {"-", 100, 2, JimExprOpBin, LAZY_NONE},
-    [JIM_EXPROP_ADD] = {"+", 100, 2, JimExprOpBin, LAZY_NONE},
+    OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP),
+    OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
+    OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
 
-    [JIM_EXPROP_ROTL] = {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
-    [JIM_EXPROP_ROTR] = {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE},
-    [JIM_EXPROP_LSHIFT] = {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
-    [JIM_EXPROP_RSHIFT] = {">>", 90, 2, JimExprOpIntBin, LAZY_NONE},
+    OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP),
+    OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
+    OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
 
-    [JIM_EXPROP_LT] = {"<", 80, 2, JimExprOpBin, LAZY_NONE},
-    [JIM_EXPROP_GT] = {">", 80, 2, JimExprOpBin, LAZY_NONE},
-    [JIM_EXPROP_LTE] = {"<=", 80, 2, JimExprOpBin, LAZY_NONE},
-    [JIM_EXPROP_GTE] = {">=", 80, 2, JimExprOpBin, LAZY_NONE},
+    OPRINIT("**", 250, 2, JimExprOpBin),
 
-    [JIM_EXPROP_NUMEQ] = {"==", 70, 2, JimExprOpBin, LAZY_NONE},
-    [JIM_EXPROP_NUMNE] = {"!=", 70, 2, JimExprOpBin, LAZY_NONE},
+    OPRINIT("eq", 60, 2, JimExprOpStrBin),
+    OPRINIT("ne", 60, 2, JimExprOpStrBin),
 
-    [JIM_EXPROP_STREQ] = {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE},
-    [JIM_EXPROP_STRNE] = {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE},
+    OPRINIT("in", 55, 2, JimExprOpStrBin),
+    OPRINIT("ni", 55, 2, JimExprOpStrBin),
 
-    [JIM_EXPROP_STRIN] = {"in", 55, 2, JimExprOpStrBin, LAZY_NONE},
-    [JIM_EXPROP_STRNI] = {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE},
+    OPRINIT("!", 150, 1, JimExprOpNumUnary),
+    OPRINIT("~", 150, 1, JimExprOpIntUnary),
+    OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
+    OPRINIT(NULL, 150, 1, JimExprOpNumUnary),
 
-    [JIM_EXPROP_BITAND] = {"&", 50, 2, JimExprOpIntBin, LAZY_NONE},
-    [JIM_EXPROP_BITXOR] = {"^", 49, 2, JimExprOpIntBin, LAZY_NONE},
-    [JIM_EXPROP_BITOR] = {"|", 48, 2, JimExprOpIntBin, LAZY_NONE},
 
-    [JIM_EXPROP_LOGICAND] = {"&&", 10, 2, NULL, LAZY_OP},
-    [JIM_EXPROP_LOGICOR] = {"||", 9, 2, NULL, LAZY_OP},
 
-    [JIM_EXPROP_TERNARY] = {"?", 5, 2, JimExprOpNull, LAZY_OP},
-    [JIM_EXPROP_COLON] = {":", 5, 2, JimExprOpNull, LAZY_OP},
+    OPRINIT("int", 200, 1, JimExprOpNumUnary),
+    OPRINIT("abs", 200, 1, JimExprOpNumUnary),
+    OPRINIT("double", 200, 1, JimExprOpNumUnary),
+    OPRINIT("round", 200, 1, JimExprOpNumUnary),
+    OPRINIT("rand", 200, 0, JimExprOpNone),
+    OPRINIT("srand", 200, 1, JimExprOpIntUnary),
 
-    /* private operators */
-    [JIM_EXPROP_TERNARY_LEFT] = {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT},
-    [JIM_EXPROP_TERNARY_RIGHT] = {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
-    [JIM_EXPROP_COLON_LEFT] = {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT},
-    [JIM_EXPROP_COLON_RIGHT] = {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
-    [JIM_EXPROP_LOGICAND_LEFT] = {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT},
-    [JIM_EXPROP_LOGICAND_RIGHT] = {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT},
-    [JIM_EXPROP_LOGICOR_LEFT] = {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT},
-    [JIM_EXPROP_LOGICOR_RIGHT] = {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT},
+#ifdef JIM_MATH_FUNCTIONS
+    OPRINIT("sin", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("cos", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("tan", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("asin", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("acos", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("atan", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("floor", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("exp", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("log", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("log10", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary),
+    OPRINIT("pow", 200, 2, JimExprOpBin),
+#endif
 };
+#undef OPRINIT
+#undef OPRINIT_LAZY
 
 #define JIM_EXPR_OPERATORS_NUM \
     (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
@@ -7789,9 +8374,12 @@ static int JimParseExpression(struct JimParserCtx *pc)
         pc->len--;
     }
 
+    /* Common case */
+    pc->tline = pc->linenr;
+    pc->tstart = pc->p;
+
     if (pc->len == 0) {
-        pc->tstart = pc->tend = pc->p;
-        pc->tline = pc->linenr;
+        pc->tend = pc->p;
         pc->tt = JIM_TT_EOL;
         pc->eof = 1;
         return JIM_OK;
@@ -7806,8 +8394,7 @@ static int JimParseExpression(struct JimParserCtx *pc)
         case ',':
             pc->tt = JIM_TT_SUBEXPR_COMMA;
 singlechar:
-            pc->tstart = pc->tend = pc->p;
-            pc->tline = pc->linenr;
+            pc->tend = pc->p;
             pc->p++;
             pc->len--;
             break;
@@ -7857,53 +8444,43 @@ singlechar:
 
 static int JimParseExprNumber(struct JimParserCtx *pc)
 {
-    int allowdot = 1;
-    int allowhex = 0;
+    char *end;
 
     /* Assume an integer for now */
     pc->tt = JIM_TT_EXPR_INT;
-    pc->tstart = pc->p;
-    pc->tline = pc->linenr;
-    while (isdigit(UCHAR(*pc->p))
-        || (allowhex && isxdigit(UCHAR(*pc->p)))
-        || (allowdot && *pc->p == '.')
-        || (pc->p - pc->tstart == 1 && *pc->tstart == '0' && (*pc->p == 'x' || *pc->p == 'X'))
-        ) {
-        if ((*pc->p == 'x') || (*pc->p == 'X')) {
-            allowhex = 1;
-            allowdot = 0;
-        }
-        if (*pc->p == '.') {
-            allowdot = 0;
-            pc->tt = JIM_TT_EXPR_DOUBLE;
-        }
-        pc->p++;
-        pc->len--;
-        if (!allowhex && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+'
-                || isdigit(UCHAR(pc->p[1])))) {
-            pc->p += 2;
-            pc->len -= 2;
+
+    jim_strtoull(pc->p, (char **)&pc->p);
+    /* Tried as an integer, but perhaps it parses as a double */
+    if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) {
+        /* Some stupid compilers insist they are cleverer that
+         * we are. Even a (void) cast doesn't prevent this warning!
+         */
+        if (strtod(pc->tstart, &end)) { /* nothing */ }
+        if (end == pc->tstart)
+            return JIM_ERR;
+        if (end > pc->p) {
+            /* Yes, double captured more chars */
             pc->tt = JIM_TT_EXPR_DOUBLE;
+            pc->p = end;
         }
     }
     pc->tend = pc->p - 1;
+    pc->len -= (pc->p - pc->tstart);
     return JIM_OK;
 }
 
 static int JimParseExprIrrational(struct JimParserCtx *pc)
 {
-    const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
-    const char **token;
+    const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL };
+    int i;
 
-    for (token = Tokens; *token != NULL; token++) {
-        int len = strlen(*token);
+    for (i = 0; irrationals[i]; i++) {
+        const char *irr = irrationals[i];
 
-        if (strncmp(*token, pc->p, len) == 0) {
-            pc->tstart = pc->p;
-            pc->tend = pc->p + len - 1;
-            pc->p += len;
-            pc->len -= len;
-            pc->tline = pc->linenr;
+        if (strncmp(irr, pc->p, 3) == 0) {
+            pc->p += 3;
+            pc->len -= 3;
+            pc->tend = pc->p - 1;
             pc->tt = JIM_TT_EXPR_DOUBLE;
             return JIM_OK;
         }
@@ -7917,18 +8494,16 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
     int bestIdx = -1, bestLen = 0;
 
     /* Try to get the longest match. */
-    for (i = JIM_TT_EXPR_OP; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
-        const char *opname;
-        int oplen;
+    for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
+        const char * const opname = Jim_ExprOperators[i].name;
+        const int oplen = Jim_ExprOperators[i].namelen;
 
-        opname = Jim_ExprOperators[i].name;
-        if (opname == NULL) {
+        if (opname == NULL || opname[0] != pc->p[0]) {
             continue;
         }
-        oplen = strlen(opname);
 
-        if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) {
-            bestIdx = i;
+        if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
+            bestIdx = i + JIM_TT_EXPR_OP;
             bestLen = oplen;
         }
     }
@@ -7949,11 +8524,9 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
             return JIM_ERR;
         }
     }
-    pc->tstart = pc->p;
     pc->tend = pc->p + bestLen - 1;
     pc->p += bestLen;
     pc->len -= bestLen;
-    pc->tline = pc->linenr;
 
     pc->tt = bestIdx;
     return JIM_OK;
@@ -7961,7 +8534,11 @@ static int JimParseExprOperator(struct JimParserCtx *pc)
 
 static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode)
 {
-    return &Jim_ExprOperators[opcode];
+    static Jim_ExprOperator dummy_op;
+    if (opcode < JIM_TT_EXPR_OP) {
+        return &dummy_op;
+    }
+    return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP];
 }
 
 const char *jim_tt_name(int type)
@@ -7976,7 +8553,7 @@ const char *jim_tt_name(int type)
         const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type);
         static char buf[20];
 
-        if (op && op->name) {
+        if (op->name) {
             return op->name;
         }
         sprintf(buf, "(%d)", type);
@@ -8002,8 +8579,8 @@ static const Jim_ObjType exprObjType = {
 /* Expr bytecode structure */
 typedef struct ExprByteCode
 {
-    int len;                    /* Length as number of tokens. */
     ScriptToken *token;         /* Tokens array. */
+    int len;                    /* Length as number of tokens. */
     int inUse;                  /* Used for sharing. */
 } ExprByteCode;
 
@@ -8054,17 +8631,15 @@ static int ExprCheckCorrectness(ExprByteCode * expr)
         ScriptToken *t = &expr->token[i];
         const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
 
-        if (op) {
-            stacklen -= op->arity;
-            if (stacklen < 0) {
-                break;
-            }
-            if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
-                ternary++;
-            }
-            else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
-                ternary--;
-            }
+        stacklen -= op->arity;
+        if (stacklen < 0) {
+            break;
+        }
+        if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) {
+            ternary++;
+        }
+        else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) {
+            ternary--;
         }
 
         /* All operations and operands add one to the stack */
@@ -8146,7 +8721,8 @@ static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseTok
 
     /* Do we need to adjust the skip count for any &L, |L, ?L or :L in the left operand? */
     for (i = leftindex - 1; i > 0; i--) {
-        if (JimExprOperatorInfoByOpcode(expr->token[i].type)->lazy == LAZY_LEFT) {
+        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type);
+        if (op->lazy == LAZY_LEFT) {
             if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) {
                 JimWideValue(expr->token[i - 1].objPtr) += 2;
             }
@@ -8355,8 +8931,9 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
      */
     for (i = 0; i < tokenlist->count; i++) {
         ParseToken *t = &tokenlist->list[i];
+        const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type);
 
-        if (JimExprOperatorInfoByOpcode(t->type)->lazy == LAZY_OP) {
+        if (op->lazy == LAZY_OP) {
             count += 2;
             /* Ternary is a lazy op but also needs reordering */
             if (t->type == JIM_EXPROP_TERNARY) {
@@ -8384,8 +8961,9 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
             case JIM_TT_DICTSUGAR:
             case JIM_TT_EXPRSUGAR:
             case JIM_TT_CMD:
-                token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
                 token->type = t->type;
+strexpr:
+                token->objPtr = Jim_NewStringObj(interp, t->token, t->len);
                 if (t->type == JIM_TT_CMD) {
                     /* Only commands need source info */
                     JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line);
@@ -8394,15 +8972,24 @@ static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList
                 break;
 
             case JIM_TT_EXPR_INT:
-                token->objPtr = Jim_NewIntObj(interp, strtoull(t->token, NULL, 0));
-                token->type = t->type;
-                expr->len++;
-                break;
-
             case JIM_TT_EXPR_DOUBLE:
-                token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, NULL));
-                token->type = t->type;
-                expr->len++;
+                {
+                    char *endptr;
+                    if (t->type == JIM_TT_EXPR_INT) {
+                        token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr));
+                    }
+                    else {
+                        token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr));
+                    }
+                    if (endptr != t->token + t->len) {
+                        /* Conversion failed, so just store it as a string */
+                        Jim_FreeNewObj(interp, token->objPtr);
+                        token->type = JIM_TT_STR;
+                        goto strexpr;
+                    }
+                    token->type = t->type;
+                    expr->len++;
+                }
                 break;
 
             case JIM_TT_SUBEXPR_START:
@@ -8559,7 +9146,7 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
 #ifdef DEBUG_SHOW_EXPR_TOKENS
     {
         int i;
-        printf("==== Expr Tokens ====\n");
+        printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj));
         for (i = 0; i < tokenlist.count; i++) {
             printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type),
                 tokenlist.list[i].len, tokenlist.list[i].token);
@@ -8567,6 +9154,12 @@ static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
     }
 #endif
 
+    if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) {
+        ScriptTokenListFree(&tokenlist);
+        Jim_DecrRefCount(interp, fileNameObj);
+        return JIM_ERR;
+    }
+
     /* Now create the expression bytecode from the tokenlist */
     expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj);
 
@@ -8617,6 +9210,20 @@ static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr)
     return (ExprByteCode *) Jim_GetIntRepPtr(objPtr);
 }
 
+#ifdef JIM_OPTIMIZATION
+static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token)
+{
+    if (token->type == JIM_TT_EXPR_INT)
+        return token->objPtr;
+    else if (token->type == JIM_TT_VAR)
+        return Jim_GetVariable(interp, token->objPtr, JIM_NONE);
+    else if (token->type == JIM_TT_DICTSUGAR)
+        return JimExpandDictSugar(interp, token->objPtr);
+    else
+        return NULL;
+}
+#endif
+
 /* -----------------------------------------------------------------------------
  * Expressions evaluation.
  * Jim uses a specialized stack-based virtual machine for expressions,
@@ -8668,29 +9275,20 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
 
         switch (expr->len) {
             case 1:
-                if (expr->token[0].type == JIM_TT_EXPR_INT) {
-                    *exprResultPtrPtr = expr->token[0].objPtr;
-                    Jim_IncrRefCount(*exprResultPtrPtr);
+                objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
+                if (objPtr) {
+                    Jim_IncrRefCount(objPtr);
+                    *exprResultPtrPtr = objPtr;
                     return JIM_OK;
                 }
-                if (expr->token[0].type == JIM_TT_VAR) {
-                    objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG);
-                    if (objPtr) {
-                        *exprResultPtrPtr = objPtr;
-                        Jim_IncrRefCount(*exprResultPtrPtr);
-                        return JIM_OK;
-                    }
-                }
                 break;
 
             case 2:
-                if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) {
-                    jim_wide wideValue;
+                if (expr->token[1].type == JIM_EXPROP_NOT) {
+                    objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
 
-                    objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
-                    if (objPtr && JimIsWide(objPtr)
-                        && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) {
-                        *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj;
+                    if (objPtr && JimIsWide(objPtr)) {
+                        *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj;
                         Jim_IncrRefCount(*exprResultPtrPtr);
                         return JIM_OK;
                     }
@@ -8698,68 +9296,44 @@ int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprRe
                 break;
 
             case 3:
-                if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT
-                        || expr->token[1].type == JIM_TT_VAR)) {
-                    switch (expr->token[2].type) {
-                        case JIM_EXPROP_LT:
-                        case JIM_EXPROP_LTE:
-                        case JIM_EXPROP_GT:
-                        case JIM_EXPROP_GTE:
-                        case JIM_EXPROP_NUMEQ:
-                        case JIM_EXPROP_NUMNE:{
-                                /* optimise ok */
-                                jim_wide wideValueA;
-                                jim_wide wideValueB;
-
-                                objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE);
-                                if (objPtr && JimIsWide(objPtr)
-                                    && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) {
-                                    if (expr->token[1].type == JIM_TT_VAR) {
-                                        objPtr =
-                                            Jim_GetVariable(interp, expr->token[1].objPtr,
-                                            JIM_NONE);
-                                    }
-                                    else {
-                                        objPtr = expr->token[1].objPtr;
-                                    }
-                                    if (objPtr && JimIsWide(objPtr)
-                                        && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) {
-                                        int cmpRes;
-
-                                        switch (expr->token[2].type) {
-                                            case JIM_EXPROP_LT:
-                                                cmpRes = wideValueA < wideValueB;
-                                                break;
-                                            case JIM_EXPROP_LTE:
-                                                cmpRes = wideValueA <= wideValueB;
-                                                break;
-                                            case JIM_EXPROP_GT:
-                                                cmpRes = wideValueA > wideValueB;
-                                                break;
-                                            case JIM_EXPROP_GTE:
-                                                cmpRes = wideValueA >= wideValueB;
-                                                break;
-                                            case JIM_EXPROP_NUMEQ:
-                                                cmpRes = wideValueA == wideValueB;
-                                                break;
-                                            case JIM_EXPROP_NUMNE:
-                                                cmpRes = wideValueA != wideValueB;
-                                                break;
-                                            default:   /*notreached */
-                                                cmpRes = 0;
-                                        }
-                                        *exprResultPtrPtr =
-                                            cmpRes ? interp->trueObj : interp->falseObj;
-                                        Jim_IncrRefCount(*exprResultPtrPtr);
-                                        return JIM_OK;
-                                    }
-                                }
-                            }
+                objPtr = JimExprIntValOrVar(interp, &expr->token[0]);
+                if (objPtr && JimIsWide(objPtr)) {
+                    Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]);
+                    if (objPtr2 && JimIsWide(objPtr2)) {
+                        jim_wide wideValueA = JimWideValue(objPtr);
+                        jim_wide wideValueB = JimWideValue(objPtr2);
+                        int cmpRes;
+                        switch (expr->token[2].type) {
+                            case JIM_EXPROP_LT:
+                                cmpRes = wideValueA < wideValueB;
+                                break;
+                            case JIM_EXPROP_LTE:
+                                cmpRes = wideValueA <= wideValueB;
+                                break;
+                            case JIM_EXPROP_GT:
+                                cmpRes = wideValueA > wideValueB;
+                                break;
+                            case JIM_EXPROP_GTE:
+                                cmpRes = wideValueA >= wideValueB;
+                                break;
+                            case JIM_EXPROP_NUMEQ:
+                                cmpRes = wideValueA == wideValueB;
+                                break;
+                            case JIM_EXPROP_NUMNE:
+                                cmpRes = wideValueA != wideValueB;
+                                break;
+                            default:
+                                goto noopt;
+                        }
+                        *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj;
+                        Jim_IncrRefCount(*exprResultPtrPtr);
+                        return JIM_OK;
                     }
                 }
                 break;
         }
     }
+noopt:
 #endif
 
     /* In order to avoid that the internal repr gets freed due to
@@ -8897,12 +9471,12 @@ int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr)
 
 typedef struct ScanFmtPartDescr
 {
-    char type;                  /* Type of conversion (e.g. c, d, f) */
-    char modifier;              /* Modify type (e.g. l - long, h - short */
-    size_t width;               /* Maximal width of input to be converted */
-    int pos;                    /* -1 - no assign, 0 - natural pos, >0 - XPG3 pos */
     char *arg;                  /* Specification of a CHARSET conversion */
     char *prefix;               /* Prefix to be scanned literally before conversion */
+    size_t width;               /* Maximal width of input to be converted */
+    int pos;                    /* -1 - no assign, 0 - natural pos, >0 - XPG3 pos */
+    char type;                  /* Type of conversion (e.g. c, d, f) */
+    char modifier;              /* Modify type (e.g. l - long, h - short */
 } ScanFmtPartDescr;
 
 /* The ScanFmtStringObj will hold the internal representation of a scanformat
@@ -8965,12 +9539,9 @@ void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
     dupPtr->typePtr = &scanFmtStringObjType;
 }
 
-void UpdateStringOfScanFmt(Jim_Obj *objPtr)
+static void UpdateStringOfScanFmt(Jim_Obj *objPtr)
 {
-    char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep;
-
-    objPtr->bytes = Jim_StrDup(bytes);
-    objPtr->length = strlen(bytes);
+    JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep);
 }
 
 /* SetScanFmtFromAny will parse a given string and create the internal
@@ -9201,7 +9772,6 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
     if (descr->prefix) {
         /* There was a prefix given before the conversion, skip it and adjust
          * the string-to-be-parsed accordingly */
-        /* XXX: Should be checking strLen, not str[pos] */
         for (i = 0; pos < strLen && descr->prefix[i]; ++i) {
             /* If prefix require, skip WS */
             if (isspace(UCHAR(descr->prefix[i])))
@@ -9268,14 +9838,11 @@ static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen
                         : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10;
 
                     /* Try to scan a number with the given base */
-                    w = strtoull(tok, &endp, base);
-                    if (endp == tok && base == 0) {
-                        /* If scanning failed, and base was undetermined, simply
-                         * put it to 10 and try once more. This should catch the
-                         * case where %i begin to parse a number prefix (e.g.
-                         * '0x' but no further digits follows. This will be
-                         * handled as a ZERO followed by a char 'x' by Tcl */
-                        w = strtoull(tok, &endp, 10);
+                    if (base == 0) {
+                        w = jim_strtoull(tok, &endp);
+                    }
+                    else {
+                        w = strtoull(tok, &endp, base);
                     }
 
                     if (endp != tok) {
@@ -9359,7 +9926,7 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjP
     emptyStr = Jim_NewEmptyStringObj(interp);
     Jim_IncrRefCount(emptyStr);
     /* Create a list and fill it with empty strings up to max specified XPG3 */
-    resultList = Jim_NewListObj(interp, 0, 0);
+    resultList = Jim_NewListObj(interp, NULL, 0);
     if (fmtObj->maxPos > 0) {
         for (i = 0; i < fmtObj->maxPos; ++i)
             Jim_ListAppendElement(interp, resultList, emptyStr);
@@ -9545,11 +10112,9 @@ static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
 #define JIM_EVAL_SINTV_LEN 8    /* static interpolation vector length */
 
 /* Handle calls to the [unknown] command */
-static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Obj *fileNameObj,
-    int linenr)
+static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    Jim_Obj **v, *sv[JIM_EVAL_SARGV_LEN];
-    int retCode;
+    int retcode;
 
     /* If JimUnknown() is recursively called too many times...
      * done here
@@ -9558,34 +10123,72 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Ob
         return JIM_ERR;
     }
 
-    /* If the [unknown] command does not exists returns
-     * just now */
-    if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
-        return JIM_ERR;
-
     /* The object interp->unknown just contains
      * the "unknown" string, it is used in order to
      * avoid to lookup the unknown command every time
-     * but instread to cache the result. */
-    if (argc + 1 <= JIM_EVAL_SARGV_LEN)
-        v = sv;
-    else
-        v = Jim_Alloc(sizeof(Jim_Obj *) * (argc + 1));
-    /* Make a copy of the arguments vector, but shifted on
-     * the right of one position. The command name of the
-     * command will be instead the first argument of the
-     * [unknown] call. */
-    memcpy(v + 1, argv, sizeof(Jim_Obj *) * argc);
-    v[0] = interp->unknown;
-    /* Call it */
+     * but instead to cache the result. */
+
+    /* If the [unknown] command does not exist ... */
+    if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL)
+        return JIM_ERR;
+
     interp->unknown_called++;
-    retCode = JimEvalObjVector(interp, argc + 1, v, fileNameObj, linenr);
+    /* XXX: Are we losing fileNameObj and linenr? */
+    retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv);
     interp->unknown_called--;
 
-    /* Clean up */
-    if (v != sv)
-        Jim_Free(v);
-    return retCode;
+    return retcode;
+}
+
+static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
+{
+    int retcode;
+    Jim_Cmd *cmdPtr;
+
+#if 0
+    printf("invoke");
+    int j;
+    for (j = 0; j < objc; j++) {
+        printf(" '%s'", Jim_String(objv[j]));
+    }
+    printf("\n");
+#endif
+
+    if (interp->framePtr->tailcallCmd) {
+        /* Special tailcall command was pre-resolved */
+        cmdPtr = interp->framePtr->tailcallCmd;
+        interp->framePtr->tailcallCmd = NULL;
+    }
+    else {
+        cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
+        if (cmdPtr == NULL) {
+            return JimUnknown(interp, objc, objv);
+        }
+        JimIncrCmdRefCount(cmdPtr);
+    }
+
+    if (interp->evalDepth == interp->maxEvalDepth) {
+        Jim_SetResultString(interp, "Infinite eval recursion", -1);
+        retcode = JIM_ERR;
+        goto out;
+    }
+    interp->evalDepth++;
+
+    /* Call it -- Make sure result is an empty object. */
+    Jim_SetEmptyResult(interp);
+    if (cmdPtr->isproc) {
+        retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
+    }
+    else {
+        interp->cmdPrivData = cmdPtr->u.native.privData;
+        retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
+    }
+    interp->evalDepth--;
+
+out:
+    JimDecrCmdRefCount(interp, cmdPtr);
+
+    return retcode;
 }
 
 /* Eval the object vector 'objv' composed of 'objc' elements.
@@ -9597,33 +10200,16 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Ob
  * list object generated by the UpdateStringOfList is made
  * in a way that ensures that every list element is a different
  * command argument. */
-static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
-    Jim_Obj *fileNameObj, int linenr)
+int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
 {
     int i, retcode;
-    Jim_Cmd *cmdPtr;
 
     /* Incr refcount of arguments. */
     for (i = 0; i < objc; i++)
         Jim_IncrRefCount(objv[i]);
-    /* Command lookup */
-    cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
-    if (cmdPtr == NULL) {
-        retcode = JimUnknown(interp, objc, objv, fileNameObj, linenr);
-    }
-    else {
-        /* Call it -- Make sure result is an empty object. */
-        JimIncrCmdRefCount(cmdPtr);
-        Jim_SetEmptyResult(interp);
-        if (cmdPtr->isproc) {
-            retcode = JimCallProcedure(interp, cmdPtr, fileNameObj, linenr, objc, objv);
-        }
-        else {
-            interp->cmdPrivData = cmdPtr->u.native.privData;
-            retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
-        }
-        JimDecrCmdRefCount(interp, cmdPtr);
-    }
+
+    retcode = JimInvokeCommand(interp, objc, objv);
+
     /* Decr refcount of arguments and return the retcode */
     for (i = 0; i < objc; i++)
         Jim_DecrRefCount(interp, objv[i]);
@@ -9631,40 +10217,32 @@ static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
     return retcode;
 }
 
-int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
-{
-    return JimEvalObjVector(interp, objc, objv, interp->emptyObj, 1);
-}
-
 /**
  * Invokes 'prefix' as a command with the objv array as arguments.
  */
 int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv)
 {
-    int i;
     int ret;
     Jim_Obj **nargv = Jim_Alloc((objc + 1) * sizeof(*nargv));
 
     nargv[0] = prefix;
-    for (i = 0; i < objc; i++) {
-        nargv[i + 1] = objv[i];
-    }
+    memcpy(&nargv[1], &objv[0], sizeof(nargv[0]) * objc);
     ret = Jim_EvalObjVector(interp, objc + 1, nargv);
     Jim_Free(nargv);
     return ret;
 }
 
-static void JimAddErrorToStack(Jim_Interp *interp, int retcode, Jim_Obj *fileNameObj, int line)
+static void JimAddErrorToStack(Jim_Interp *interp, int retcode, ScriptObj *script)
 {
     int rc = retcode;
 
     if (rc == JIM_ERR && !interp->errorFlag) {
         /* This is the first error, so save the file/line information and reset the stack */
         interp->errorFlag = 1;
-        Jim_IncrRefCount(fileNameObj);
+        Jim_IncrRefCount(script->fileNameObj);
         Jim_DecrRefCount(interp, interp->errorFileNameObj);
-        interp->errorFileNameObj = fileNameObj;
-        interp->errorLine = line;
+        interp->errorFileNameObj = script->fileNameObj;
+        interp->errorLine = script->linenr;
 
         JimResetStackTrace(interp);
         /* Always add a level where the error first occurs */
@@ -9675,13 +10253,13 @@ static void JimAddErrorToStack(Jim_Interp *interp, int retcode, Jim_Obj *fileNam
     if (rc == JIM_ERR && interp->addStackTrace > 0) {
         /* Add the stack info for the current level */
 
-        JimAppendStackTrace(interp, Jim_String(interp->errorProc), fileNameObj, line);
+        JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
 
         /* Note: if we didn't have a filename for this level,
          * don't clear the addStackTrace flag
          * so we can pick it up at the next level
          */
-        if (Jim_Length(fileNameObj)) {
+        if (Jim_Length(script->fileNameObj)) {
             interp->addStackTrace = 0;
         }
 
@@ -9697,39 +10275,6 @@ static void JimAddErrorToStack(Jim_Interp *interp, int retcode, Jim_Obj *fileNam
     }
 }
 
-/* And delete any local procs */
-static void JimDeleteLocalProcs(Jim_Interp *interp)
-{
-    if (interp->localProcs) {
-        char *procname;
-
-        while ((procname = Jim_StackPop(interp->localProcs)) != NULL) {
-            /* If there is a pushed command, find it */
-            Jim_Cmd *prevCmd = NULL;
-            Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, procname);
-            if (he) {
-                Jim_Cmd *cmd = (Jim_Cmd *)he->u.val;
-                if (cmd->isproc && cmd->u.proc.prevCmd) {
-                    prevCmd = cmd->u.proc.prevCmd;
-                    cmd->u.proc.prevCmd = NULL;
-                }
-            }
-
-            /* Delete the local proc */
-            Jim_DeleteCommand(interp, procname);
-
-            if (prevCmd) {
-                /* And restore the pushed command */
-                Jim_AddHashEntry(&interp->commands, procname, prevCmd);
-            }
-            Jim_Free(procname);
-        }
-        Jim_FreeStack(interp->localProcs);
-        Jim_Free(interp->localProcs);
-        interp->localProcs = NULL;
-    }
-}
-
 static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr)
 {
     Jim_Obj *objPtr;
@@ -9844,10 +10389,15 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
         && token[2].type == JIM_TT_VAR) {
         /* May be able to do fast interpolated object -> dictSubst */
         objPtr->typePtr = &interpolatedObjType;
-        objPtr->internalRep.twoPtrValue.ptr1 = (void *)token;
-        objPtr->internalRep.twoPtrValue.ptr2 = intv[2];
+        objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr;
+        objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2];
         Jim_IncrRefCount(intv[2]);
     }
+    else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) {
+        /* The first interpolated token is source, so preserve the source info */
+        JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber);
+    }
+
 
     s = objPtr->bytes = Jim_Alloc(totlen + 1);
     objPtr->length = totlen;
@@ -9868,26 +10418,28 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
 }
 
 
-/* If listPtr is a list, call JimEvalObjVector() with the given source info.
- * Otherwise eval with Jim_EvalObj()
+/* listPtr *must* be a list.
+ * The contents of the list is evaluated with the first element as the command and
+ * the remaining elements as the arguments.
  */
-static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *fileNameObj, int linenr)
+static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
 {
-    if (!Jim_IsList(listPtr)) {
-        return Jim_EvalObj(interp, listPtr);
-    }
-    else {
-        int retcode = JIM_OK;
+    int retcode = JIM_OK;
 
-        if (listPtr->internalRep.listValue.len) {
-            Jim_IncrRefCount(listPtr);
-            retcode = JimEvalObjVector(interp,
-                listPtr->internalRep.listValue.len,
-                listPtr->internalRep.listValue.ele, fileNameObj, linenr);
-            Jim_DecrRefCount(interp, listPtr);
-        }
-        return retcode;
+    if (listPtr->internalRep.listValue.len) {
+        Jim_IncrRefCount(listPtr);
+        retcode = JimInvokeCommand(interp,
+            listPtr->internalRep.listValue.len,
+            listPtr->internalRep.listValue.ele);
+        Jim_DecrRefCount(interp, listPtr);
     }
+    return retcode;
+}
+
+int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
+{
+    SetListFromAny(interp, listPtr);
+    return JimEvalObjList(interp, listPtr);
 }
 
 int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
@@ -9897,23 +10449,27 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
     ScriptToken *token;
     int retcode = JIM_OK;
     Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL;
-    int linenr = 0;
-
-    interp->errorFlag = 0;
+    Jim_Obj *prevScriptObj;
 
     /* If the object is of type "list", with no string rep we can call
      * a specialized version of Jim_EvalObj() */
     if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) {
-        return JimEvalObjList(interp, scriptObjPtr, interp->emptyObj, 1);
+        return JimEvalObjList(interp, scriptObjPtr);
     }
 
     Jim_IncrRefCount(scriptObjPtr);     /* Make sure it's shared. */
     script = Jim_GetScript(interp, scriptObjPtr);
+    if (script == NULL) {
+        Jim_DecrRefCount(interp, scriptObjPtr);
+        return JIM_ERR;
+    }
 
     /* Reset the interpreter result. This is useful to
      * return the empty result in the case of empty program. */
     Jim_SetEmptyResult(interp);
 
+    token = script->token;
+
 #ifdef JIM_OPTIMIZATION
     /* Check for one of the following common scripts used by for, while
      *
@@ -9925,12 +10481,12 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
         return JIM_OK;
     }
     if (script->len == 3
-        && script->token[1].objPtr->typePtr == &commandObjType
-        && script->token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0
-        && script->token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand
-        && script->token[2].objPtr->typePtr == &variableObjType) {
+        && token[1].objPtr->typePtr == &commandObjType
+        && token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0
+        && token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand
+        && token[2].objPtr->typePtr == &variableObjType) {
 
-        Jim_Obj *objPtr = Jim_GetVariable(interp, script->token[2].objPtr, JIM_NONE);
+        Jim_Obj *objPtr = Jim_GetVariable(interp, token[2].objPtr, JIM_NONE);
 
         if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) {
             JimWideValue(objPtr)++;
@@ -9953,7 +10509,11 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
      * inUse field of the script internal rep structure. */
     script->inUse++;
 
-    token = script->token;
+    /* Stash the current script */
+    prevScriptObj = interp->currentScriptObj;
+    interp->currentScriptObj = scriptObjPtr;
+
+    interp->errorFlag = 0;
     argv = sargv;
 
     /* Execute every command sequentially until the end of the script
@@ -9962,11 +10522,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
     for (i = 0; i < script->len && retcode == JIM_OK; ) {
         int argc;
         int j;
-        Jim_Cmd *cmd;
 
         /* First token of the line is always JIM_TT_LINE */
         argc = token[i].objPtr->internalRep.scriptLineValue.argc;
-        linenr = token[i].objPtr->internalRep.scriptLineValue.line;
+        script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
 
         /* Allocate the arguments vector if required */
         if (argc > JIM_EVAL_SARGV_LEN)
@@ -10077,27 +10636,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
         }
 
         if (retcode == JIM_OK && argc) {
-            /* Lookup the command to call */
-            cmd = Jim_GetCommand(interp, argv[0], JIM_ERRMSG);
-            if (cmd != NULL) {
-                /* Call it -- Make sure result is an empty object. */
-                JimIncrCmdRefCount(cmd);
-                Jim_SetEmptyResult(interp);
-                if (cmd->isproc) {
-                    retcode =
-                        JimCallProcedure(interp, cmd, script->fileNameObj, linenr, argc, argv);
-                } else {
-                    interp->cmdPrivData = cmd->u.native.privData;
-                    retcode = cmd->u.native.cmdProc(interp, argc, argv);
-                }
-                JimDecrCmdRefCount(interp, cmd);
-            }
-            else {
-                /* Call [unknown] */
-                retcode = JimUnknown(interp, argc, argv, script->fileNameObj, linenr);
-            }
-            if (interp->signal_level && interp->sigmask) {
-                /* Check for a signal after each command */
+            /* Invoke the command */
+            retcode = JimInvokeCommand(interp, argc, argv);
+            /* Check for a signal after each command */
+            if (Jim_CheckSignal(interp)) {
                 retcode = JIM_SIGNAL;
             }
         }
@@ -10114,7 +10656,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
     }
 
     /* Possibly add to the error stack trace */
-    JimAddErrorToStack(interp, retcode, script->fileNameObj, linenr);
+    JimAddErrorToStack(interp, retcode, script);
+
+    /* Restore the current script */
+    interp->currentScriptObj = prevScriptObj;
 
     /* Note that we don't have to decrement inUse, because the
      * following code transfers our use of the reference again to
@@ -10137,7 +10682,7 @@ static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argVa
         Jim_Obj *objPtr;
         Jim_CallFrame *savedCallFrame = interp->framePtr;
 
-        interp->framePtr = interp->framePtr->parentCallFrame;
+        interp->framePtr = interp->framePtr->parent;
         objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG);
         interp->framePtr = savedCallFrame;
         if (!objPtr) {
@@ -10147,7 +10692,7 @@ static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argVa
         /* It exists, so perform the binding. */
         objPtr = Jim_NewStringObj(interp, varname + 1, -1);
         Jim_IncrRefCount(objPtr);
-        retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parentCallFrame);
+        retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent);
         Jim_DecrRefCount(interp, objPtr);
     }
     else {
@@ -10177,7 +10722,7 @@ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cm
             }
             else {
                 /* We have plain args */
-                Jim_AppendString(interp, argmsg, "?argument ...?", -1);
+                Jim_AppendString(interp, argmsg, "?arg...?", -1);
             }
         }
         else {
@@ -10187,7 +10732,11 @@ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cm
                 Jim_AppendString(interp, argmsg, "?", 1);
             }
             else {
-                Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr);
+                const char *arg = Jim_String(cmd->u.proc.arglist[i].nameObjPtr);
+                if (*arg == '&') {
+                    arg++;
+                }
+                Jim_AppendString(interp, argmsg, arg, -1);
             }
         }
     }
@@ -10195,6 +10744,45 @@ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cm
     Jim_FreeNewObj(interp, argmsg);
 }
 
+#ifdef jim_ext_namespace
+/*
+ * [namespace eval]
+ */
+int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
+{
+    Jim_CallFrame *callFramePtr;
+    int retcode;
+
+    /* Create a new callframe */
+    callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
+    callFramePtr->argv = &interp->emptyObj;
+    callFramePtr->argc = 0;
+    callFramePtr->procArgsObjPtr = NULL;
+    callFramePtr->procBodyObjPtr = scriptObj;
+    callFramePtr->staticVars = NULL;
+    callFramePtr->fileNameObj = interp->emptyObj;
+    callFramePtr->line = 0;
+    Jim_IncrRefCount(scriptObj);
+    interp->framePtr = callFramePtr;
+
+    /* Check if there are too nested calls */
+    if (interp->framePtr->level == interp->maxCallFrameDepth) {
+        Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
+        retcode = JIM_ERR;
+    }
+    else {
+        /* Eval the body */
+        retcode = Jim_EvalObj(interp, scriptObj);
+    }
+
+    /* Destroy the callframe */
+    interp->framePtr = interp->framePtr->parent;
+    JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
+
+    return retcode;
+}
+#endif
+
 /* Call a procedure implemented in Tcl.
  * It's possible to speed-up a lot this function, currently
  * the callframes are not cached, but allocated and
@@ -10203,12 +10791,11 @@ static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cm
  *
  * This can be fixed just implementing callframes caching
  * in JimCreateCallFrame() and JimFreeCallFrame(). */
-static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr, int argc,
-    Jim_Obj *const *argv)
+static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
 {
     Jim_CallFrame *callFramePtr;
-    Jim_Stack *prevLocalProcs;
     int i, d, retcode, optargs;
+    ScriptObj *script;
 
     /* Check arity */
     if (argc - 1 < cmd->u.proc.reqArity ||
@@ -10217,21 +10804,30 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameO
         return JIM_ERR;
     }
 
+    if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) {
+        /* Optimise for procedure with no body - useful for optional debugging */
+        return JIM_OK;
+    }
+
     /* Check if there are too nested calls */
-    if (interp->framePtr->level == interp->maxNestingDepth) {
+    if (interp->framePtr->level == interp->maxCallFrameDepth) {
         Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
         return JIM_ERR;
     }
 
     /* Create a new callframe */
-    callFramePtr = JimCreateCallFrame(interp, interp->framePtr);
+    callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj);
     callFramePtr->argv = argv;
     callFramePtr->argc = argc;
     callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr;
     callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
     callFramePtr->staticVars = cmd->u.proc.staticVars;
-    callFramePtr->fileNameObj = fileNameObj;
-    callFramePtr->line = linenr;
+
+    /* Remember where we were called from. */
+    script = Jim_GetScript(interp, interp->currentScriptObj);
+    callFramePtr->fileNameObj = script->fileNameObj;
+    callFramePtr->line = script->linenr;
+
     Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
     Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
     interp->framePtr = callFramePtr;
@@ -10278,35 +10874,45 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameO
         }
     }
 
-    /* Install a new stack for local procs */
-    prevLocalProcs = interp->localProcs;
-    interp->localProcs = NULL;
-
     /* Eval the body */
     retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr);
 
-    /* Delete any local procs */
-    JimDeleteLocalProcs(interp);
-    interp->localProcs = prevLocalProcs;
-
 badargset:
-    /* Destroy the callframe */
-    interp->framePtr = interp->framePtr->parentCallFrame;
-    if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) {
-        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE);
-    }
-    else {
-        JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT);
-    }
-    /* Handle the JIM_EVAL return code */
-    while (retcode == JIM_EVAL) {
-        Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
 
-        Jim_IncrRefCount(resultScriptObjPtr);
-        /* Should be a list! */
-        retcode = JimEvalObjList(interp, resultScriptObjPtr, fileNameObj, linenr);
-        Jim_DecrRefCount(interp, resultScriptObjPtr);
+    /* Free the callframe */
+    interp->framePtr = interp->framePtr->parent;
+    JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
+
+    if (interp->framePtr->tailcallObj) {
+        /* If a tailcall is already being executed, merge this tailcall with that one */
+        if (interp->framePtr->tailcall++ == 0) {
+            /* No current tailcall in this frame, so invoke the tailcall command */
+            do {
+                Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
+
+                interp->framePtr->tailcallObj = NULL;
+
+                if (retcode == JIM_EVAL) {
+                    retcode = Jim_EvalObjList(interp, tailcallObj);
+                    if (retcode == JIM_RETURN) {
+                        /* If the result of the tailcall is 'return', push
+                         * it up to the caller
+                         */
+                        interp->returnLevel++;
+                    }
+                }
+                Jim_DecrRefCount(interp, tailcallObj);
+            } while (interp->framePtr->tailcallObj);
+
+            /* If the tailcall chain finished early, may need to manually discard the command */
+            if (interp->framePtr->tailcallCmd) {
+                JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
+                interp->framePtr->tailcallCmd = NULL;
+            }
+        }
+        interp->framePtr->tailcall--;
     }
+
     /* Handle the JIM_RETURN return code */
     if (retcode == JIM_RETURN) {
         if (--interp->returnLevel <= 0) {
@@ -10321,6 +10927,7 @@ badargset:
         interp->errorProc = argv[0];
         Jim_IncrRefCount(interp->errorProc);
     }
+
     return retcode;
 }
 
@@ -10392,7 +10999,6 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
     struct stat sb;
     int retcode;
     int readlen;
-    struct JimParseResult result;
 
     if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) {
         Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
@@ -10407,39 +11013,21 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
     readlen = fread(buf, 1, sb.st_size, fp);
     if (ferror(fp)) {
         fclose(fp);
-        Jim_Free(buf);
-        Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno));
-        return JIM_ERR;
-    }
-    fclose(fp);
-    buf[readlen] = 0;
-
-    scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
-    JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
-    Jim_IncrRefCount(scriptObjPtr);
-
-    /* Now check the script for unmatched braces, etc. */
-    if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) {
-        const char *msg;
-        char linebuf[20];
-
-        switch (result.missing) {
-            case '[':
-                msg = "unmatched \"[\"";
-                break;
-            case '{':
-                msg = "missing close-brace";
-                break;
-            case '"':
-            default:
-                msg = "missing quote";
-                break;
-        }
+        Jim_Free(buf);
+        Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno));
+        return JIM_ERR;
+    }
+    fclose(fp);
+    buf[readlen] = 0;
 
-        snprintf(linebuf, sizeof(linebuf), "%d", result.line);
+    scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
+    JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
+    Jim_IncrRefCount(scriptObjPtr);
 
-        Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s",
-            msg, filename, linebuf);
+    /* Now check the script for unmatched braces, etc. */
+    if (Jim_GetScript(interp, scriptObjPtr) == NULL) {
+        /* EvalFile changes context, so add a stack frame here */
+        JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr));
         Jim_DecrRefCount(interp, scriptObjPtr);
         return JIM_ERR;
     }
@@ -10472,74 +11060,45 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
 /* -----------------------------------------------------------------------------
  * Subst
  * ---------------------------------------------------------------------------*/
-static int JimParseSubstStr(struct JimParserCtx *pc)
+static void JimParseSubst(struct JimParserCtx *pc, int flags)
 {
     pc->tstart = pc->p;
     pc->tline = pc->linenr;
-    while (pc->len && *pc->p != '$' && *pc->p != '[') {
-        if (*pc->p == '\\' && pc->len > 1) {
-            pc->p++;
-            pc->len--;
-        }
-        pc->p++;
-        pc->len--;
-    }
-    pc->tend = pc->p - 1;
-    pc->tt = JIM_TT_ESC;
-    return JIM_OK;
-}
-
-static int JimParseSubst(struct JimParserCtx *pc, int flags)
-{
-    int retval;
 
     if (pc->len == 0) {
-        pc->tstart = pc->tend = pc->p;
-        pc->tline = pc->linenr;
+        pc->tend = pc->p;
         pc->tt = JIM_TT_EOL;
         pc->eof = 1;
-        return JIM_OK;
+        return;
     }
-    switch (*pc->p) {
-        case '[':
-            retval = JimParseCmd(pc);
-            if (flags & JIM_SUBST_NOCMD) {
-                pc->tstart--;
-                pc->tend++;
-                pc->tt = (flags & JIM_SUBST_NOESC) ? JIM_TT_STR : JIM_TT_ESC;
-            }
-            return retval;
-            break;
-        case '$':
-            if (JimParseVar(pc) == JIM_ERR) {
-                pc->tstart = pc->tend = pc->p++;
-                pc->len--;
-                pc->tline = pc->linenr;
-                pc->tt = JIM_TT_STR;
-            }
-            else {
-                if (flags & JIM_SUBST_NOVAR) {
-                    pc->tstart--;
-                    if (flags & JIM_SUBST_NOESC)
-                        pc->tt = JIM_TT_STR;
-                    else
-                        pc->tt = JIM_TT_ESC;
-                    if (*pc->tstart == '{') {
-                        pc->tstart--;
-                        if (*(pc->tend + 1))
-                            pc->tend++;
-                    }
-                }
-            }
+    if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) {
+        JimParseCmd(pc);
+        return;
+    }
+    if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
+        if (JimParseVar(pc) == JIM_OK) {
+            return;
+        }
+        /* Not a var, so treat as a string */
+        pc->tstart = pc->p;
+        flags |= JIM_SUBST_NOVAR;
+    }
+    while (pc->len) {
+        if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) {
             break;
-        default:
-            retval = JimParseSubstStr(pc);
-            if (flags & JIM_SUBST_NOESC)
-                pc->tt = JIM_TT_STR;
-            return retval;
+        }
+        if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) {
             break;
+        }
+        if (*pc->p == '\\' && pc->len > 1) {
+            pc->p++;
+            pc->len--;
+        }
+        pc->p++;
+        pc->len--;
     }
-    return JIM_OK;
+    pc->tend = pc->p - 1;
+    pc->tt = (flags & JIM_SUBST_NOESC) ? JIM_TT_STR : JIM_TT_ESC;
 }
 
 /* The subst object type reuses most of the data structures and functions
@@ -10636,106 +11195,128 @@ int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPt
  * ---------------------------------------------------------------------------*/
 void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
 {
-    int i;
-    Jim_Obj *objPtr = Jim_NewEmptyStringObj(interp);
+    Jim_Obj *objPtr;
+    Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc);
 
-    Jim_AppendString(interp, objPtr, "wrong # args: should be \"", -1);
-    for (i = 0; i < argc; i++) {
-        Jim_AppendObj(interp, objPtr, argv[i]);
-        if (!(i + 1 == argc && msg[0] == '\0'))
-            Jim_AppendString(interp, objPtr, " ", 1);
+    if (*msg) {
+        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
     }
-    Jim_AppendString(interp, objPtr, msg, -1);
-    Jim_AppendString(interp, objPtr, "\"", 1);
-    Jim_SetResult(interp, objPtr);
+    Jim_IncrRefCount(listObjPtr);
+    objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
+    Jim_DecrRefCount(interp, listObjPtr);
+
+    Jim_IncrRefCount(objPtr);
+    Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
+    Jim_DecrRefCount(interp, objPtr);
 }
 
-#define JimTrivialMatch(pattern)       (strpbrk((pattern), "*[?\\") == NULL)
+/**
+ * May add the key and/or value to the list.
+ */
+typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
+    Jim_HashEntry *he, int type);
+
+#define JimTrivialMatch(pattern)    (strpbrk((pattern), "*[?\\") == NULL)
 
-/* type is: 0=commands, 1=procs, 2=channels */
-static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type)
+/**
+ * For each key of the hash table 'ht' (with string keys) which matches the glob pattern (all if NULL),
+ * invoke the callback to add entries to a list.
+ * Returns the list.
+ */
+static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
+    JimHashtableIteratorCallbackType *callback, int type)
 {
-    Jim_HashTableIterator *htiter;
     Jim_HashEntry *he;
     Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
 
     /* Check for the non-pattern case. We can do this much more efficiently. */
     if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) {
-        Jim_Cmd *cmdPtr = Jim_GetCommand(interp, patternObjPtr, JIM_NONE);
-        if (cmdPtr) {
-            if (type == 1 && !cmdPtr->isproc) {
-                /* not a proc */
-            }
-            else if (type == 2 && !Jim_AioFilehandle(interp, patternObjPtr)) {
-                /* not a channel */
-            }
-            else {
-                Jim_ListAppendElement(interp, listObjPtr, patternObjPtr);
+        he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr));
+        if (he) {
+            callback(interp, listObjPtr, he, type);
+        }
+    }
+    else {
+        Jim_HashTableIterator htiter;
+        JimInitHashTableIterator(ht, &htiter);
+        while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+            if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
+                callback(interp, listObjPtr, he, type);
             }
         }
-        return listObjPtr;
     }
+    return listObjPtr;
+}
 
-    htiter = Jim_GetHashTableIterator(&interp->commands);
-    while ((he = Jim_NextHashEntry(htiter)) != NULL) {
-        Jim_Cmd *cmdPtr = he->u.val;
-        Jim_Obj *cmdNameObj;
+/* Keep these in order */
+#define JIM_CMDLIST_COMMANDS 0
+#define JIM_CMDLIST_PROCS 1
+#define JIM_CMDLIST_CHANNELS 2
 
-        if (type == 1 && !cmdPtr->isproc) {
-            /* not a proc */
-            continue;
-        }
-        if (patternObjPtr && !JimStringMatch(interp, patternObjPtr, he->key, 0))
-            continue;
+/**
+ * Adds matching command names (procs, channels) to the list.
+ */
+static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
+    Jim_HashEntry *he, int type)
+{
+    Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he);
+    Jim_Obj *objPtr;
 
-        cmdNameObj = Jim_NewStringObj(interp, he->key, -1);
+    if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
+        /* not a proc */
+        return;
+    }
 
-        /* Is it a channel? */
-        if (type == 2 && !Jim_AioFilehandle(interp, cmdNameObj)) {
-            Jim_FreeNewObj(interp, cmdNameObj);
-            continue;
-        }
+    objPtr = Jim_NewStringObj(interp, he->key, -1);
+    Jim_IncrRefCount(objPtr);
 
-        Jim_ListAppendElement(interp, listObjPtr, cmdNameObj);
+    if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, objPtr)) {
+        Jim_ListAppendElement(interp, listObjPtr, objPtr);
     }
-    Jim_FreeHashTableIterator(htiter);
-    return listObjPtr;
+    Jim_DecrRefCount(interp, objPtr);
+}
+
+/* type is JIM_CMDLIST_xxx */
+static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type)
+{
+    return JimHashtablePatternMatch(interp, &interp->commands, patternObjPtr, JimCommandMatch, type);
 }
 
-/* Keep this in order */
+/* Keep these in order */
 #define JIM_VARLIST_GLOBALS 0
 #define JIM_VARLIST_LOCALS 1
 #define JIM_VARLIST_VARS 2
 
-static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode)
+#define JIM_VARLIST_VALUES 0x1000
+
+/**
+ * Adds matching variable names to the list.
+ */
+static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
+    Jim_HashEntry *he, int type)
 {
-    Jim_HashTableIterator *htiter;
-    Jim_HashEntry *he;
-    Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
+    Jim_Var *varPtr = Jim_GetHashEntryVal(he);
 
-    if (mode == JIM_VARLIST_GLOBALS) {
-        htiter = Jim_GetHashTableIterator(&interp->topFramePtr->vars);
+    if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) {
+        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
+        if (type & JIM_VARLIST_VALUES) {
+            Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr);
+        }
     }
-    else {
+}
+
+/* mode is JIM_VARLIST_xxx */
+static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode)
+{
+    if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) {
         /* For [info locals], if we are at top level an emtpy list
          * is returned. I don't agree, but we aim at compatibility (SS) */
-        if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr)
-            return listObjPtr;
-        htiter = Jim_GetHashTableIterator(&interp->framePtr->vars);
+        return interp->emptyObj;
     }
-    while ((he = Jim_NextHashEntry(htiter)) != NULL) {
-        Jim_Var *varPtr = (Jim_Var *)he->u.val;
-
-        if (mode == JIM_VARLIST_LOCALS) {
-            if (varPtr->linkFramePtr != NULL)
-                continue;
-        }
-        if (patternObjPtr && !JimStringMatch(interp, patternObjPtr, he->key, 0))
-            continue;
-        Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1));
+    else {
+        Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr;
+        return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, mode);
     }
-    Jim_FreeHashTableIterator(htiter);
-    return listObjPtr;
 }
 
 static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr,
@@ -11053,7 +11634,6 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
         ScriptObj *incrScript;
         ExprByteCode *expr;
         jim_wide stop, currentVal;
-        unsigned jim_wide procEpoch;
         Jim_Obj *objPtr;
         int cmpOffset;
 
@@ -11062,7 +11642,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
         incrScript = Jim_GetScript(interp, argv[3]);
 
         /* Ensure proper lengths to start */
-        if (incrScript->len != 3 || !expr || expr->len != 3) {
+        if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) {
             goto evalstart;
         }
         /* Ensure proper token types. */
@@ -11106,7 +11686,6 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
         }
 
         /* Initialization */
-        procEpoch = interp->procEpoch;
         varNamePtr = expr->token[0].objPtr;
         Jim_IncrRefCount(varNamePtr);
 
@@ -11136,11 +11715,6 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv
             retval = Jim_EvalObj(interp, argv[4]);
             if (retval == JIM_OK || retval == JIM_CONTINUE) {
                 retval = JIM_OK;
-                /* If there was a change in procedures/command continue
-                 * with the usual [for] command implementation */
-                if (procEpoch != interp->procEpoch) {
-                    goto evalnext;
-                }
 
                 objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG);
 
@@ -11266,100 +11840,139 @@ static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
     return retval;
 }
 
+/* List iterators make it easy to iterate over a list.
+ * At some point iterators will be expanded to support generators.
+ */
+typedef struct {
+    Jim_Obj *objPtr;
+    int idx;
+} Jim_ListIter;
+
+/**
+ * Initialise the iterator at the start of the list.
+ */
+static void JimListIterInit(Jim_ListIter *iter, Jim_Obj *objPtr)
+{
+    iter->objPtr = objPtr;
+    iter->idx = 0;
+}
+
+/**
+ * Returns the next object from the list, or NULL on end-of-list.
+ */
+static Jim_Obj *JimListIterNext(Jim_Interp *interp, Jim_ListIter *iter)
+{
+    if (iter->idx >= Jim_ListLength(interp, iter->objPtr)) {
+        return NULL;
+    }
+    return iter->objPtr->internalRep.listValue.ele[iter->idx++];
+}
+
+/**
+ * Returns 1 if end-of-list has been reached.
+ */
+static int JimListIterDone(Jim_Interp *interp, Jim_ListIter *iter)
+{
+    return iter->idx >= Jim_ListLength(interp, iter->objPtr);
+}
+
 /* foreach + lmap implementation. */
 static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap)
 {
-    int result = JIM_ERR, i, nbrOfLists, *listsIdx, *listsEnd;
-    int nbrOfLoops = 0;
-    Jim_Obj *emptyStr, *script, *mapRes = NULL;
+    int result = JIM_OK;
+    int i, numargs;
+    Jim_ListIter twoiters[2];   /* Avoid allocation for a single list */
+    Jim_ListIter *iters;
+    Jim_Obj *script;
+    Jim_Obj *resultObj;
 
     if (argc < 4 || argc % 2 != 0) {
         Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
         return JIM_ERR;
     }
+    script = argv[argc - 1];    /* Last argument is a script */
+    numargs = (argc - 1 - 1);    /* argc - 'foreach' - script */
+
+    if (numargs == 2) {
+        iters = twoiters;
+    }
+    else {
+        iters = Jim_Alloc(numargs * sizeof(*iters));
+    }
+    for (i = 0; i < numargs; i++) {
+        JimListIterInit(&iters[i], argv[i + 1]);
+        if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) {
+            result = JIM_ERR;
+        }
+    }
+    if (result != JIM_OK) {
+        Jim_SetResultString(interp, "foreach varlist is empty", -1);
+        return result;
+    }
+
     if (doMap) {
-        mapRes = Jim_NewListObj(interp, NULL, 0);
-        Jim_IncrRefCount(mapRes);
+        resultObj = Jim_NewListObj(interp, NULL, 0);
     }
-    emptyStr = Jim_NewEmptyStringObj(interp);
-    Jim_IncrRefCount(emptyStr);
-    script = argv[argc - 1];    /* Last argument is a script */
-    nbrOfLists = (argc - 1 - 1) / 2;    /* argc - 'foreach' - script */
-    listsIdx = (int *)Jim_Alloc(nbrOfLists * sizeof(int));
-    listsEnd = (int *)Jim_Alloc(nbrOfLists * 2 * sizeof(int));
-    /* Initialize iterators and remember max nbr elements each list */
-    memset(listsIdx, 0, nbrOfLists * sizeof(int));
-    /* Remember lengths of all lists and calculate how much rounds to loop */
-    for (i = 0; i < nbrOfLists * 2; i += 2) {
-        div_t cnt;
-        int count;
-
-        listsEnd[i] = Jim_ListLength(interp, argv[i + 1]);
-        listsEnd[i + 1] = Jim_ListLength(interp, argv[i + 2]);
-        if (listsEnd[i] == 0) {
-            Jim_SetResultString(interp, "foreach varlist is empty", -1);
-            goto err;
+    else {
+        resultObj = interp->emptyObj;
+    }
+    Jim_IncrRefCount(resultObj);
+
+    while (1) {
+        /* Have we expired all lists? */
+        for (i = 0; i < numargs; i += 2) {
+            if (!JimListIterDone(interp, &iters[i + 1])) {
+                break;
+            }
         }
-        cnt = div(listsEnd[i + 1], listsEnd[i]);
-        count = cnt.quot + (cnt.rem ? 1 : 0);
-        if (count > nbrOfLoops)
-            nbrOfLoops = count;
-    }
-    for (; nbrOfLoops-- > 0;) {
-        for (i = 0; i < nbrOfLists; ++i) {
-            int varIdx = 0, var = i * 2;
-
-            while (varIdx < listsEnd[var]) {
-                Jim_Obj *varName, *ele;
-                int lst = i * 2 + 1;
-
-                /* List index operations below can't fail */
-                Jim_ListIndex(interp, argv[var + 1], varIdx, &varName, JIM_NONE);
-                if (listsIdx[i] < listsEnd[lst]) {
-                    Jim_ListIndex(interp, argv[lst + 1], listsIdx[i], &ele, JIM_NONE);
-                    /* Avoid shimmering */
-                    Jim_IncrRefCount(ele);
-                    result = Jim_SetVariable(interp, varName, ele);
-                    Jim_DecrRefCount(interp, ele);
-                    if (result == JIM_OK) {
-                        ++listsIdx[i];  /* Remember next iterator of current list */
-                        ++varIdx;       /* Next variable */
-                        continue;
-                    }
+        if (i == numargs) {
+            /* All done */
+            break;
+        }
+
+        /* For each list */
+        for (i = 0; i < numargs; i += 2) {
+            Jim_Obj *varName;
+
+            /* foreach var */
+            JimListIterInit(&iters[i], argv[i + 1]);
+            while ((varName = JimListIterNext(interp, &iters[i])) != NULL) {
+                Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]);
+                if (!valObj) {
+                    /* Ran out, so store the empty string */
+                    valObj = interp->emptyObj;
                 }
-                else if (Jim_SetVariable(interp, varName, emptyStr) == JIM_OK) {
-                    ++varIdx;   /* Next variable */
-                    continue;
+                /* Avoid shimmering */
+                Jim_IncrRefCount(valObj);
+                result = Jim_SetVariable(interp, varName, valObj);
+                Jim_DecrRefCount(interp, valObj);
+                if (result != JIM_OK) {
+                    goto err;
                 }
-                goto err;
             }
         }
         switch (result = Jim_EvalObj(interp, script)) {
             case JIM_OK:
-                if (doMap)
-                    Jim_ListAppendElement(interp, mapRes, interp->result);
+                if (doMap) {
+                    Jim_ListAppendElement(interp, resultObj, interp->result);
+                }
                 break;
             case JIM_CONTINUE:
                 break;
             case JIM_BREAK:
                 goto out;
-                break;
             default:
                 goto err;
         }
     }
   out:
     result = JIM_OK;
-    if (doMap)
-        Jim_SetResult(interp, mapRes);
-    else
-        Jim_SetEmptyResult(interp);
+    Jim_SetResult(interp, resultObj);
   err:
-    if (doMap)
-        Jim_DecrRefCount(interp, mapRes);
-    Jim_DecrRefCount(interp, emptyStr);
-    Jim_Free(listsIdx);
-    Jim_Free(listsEnd);
+    Jim_DecrRefCount(interp, resultObj);
+    if (numargs > 2) {
+        Jim_Free(iters);
+    }
     return result;
 }
 
@@ -11375,6 +11988,39 @@ static int Jim_LmapCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
     return JimForeachMapHelper(interp, argc, argv, 1);
 }
 
+/* [lassign] */
+static int Jim_LassignCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    int result = JIM_ERR;
+    int i;
+    Jim_ListIter iter;
+    Jim_Obj *resultObj;
+
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "varList list ?varName ...?");
+        return JIM_ERR;
+    }
+
+    JimListIterInit(&iter, argv[1]);
+
+    for (i = 2; i < argc; i++) {
+        Jim_Obj *valObj = JimListIterNext(interp, &iter);
+        result = Jim_SetVariable(interp, argv[i], valObj ? valObj : interp->emptyObj);
+        if (result != JIM_OK) {
+            return result;
+        }
+    }
+
+    resultObj = Jim_NewListObj(interp, NULL, 0);
+    while (!JimListIterDone(interp, &iter)) {
+        Jim_ListAppendElement(interp, resultObj, JimListIterNext(interp, &iter));
+    }
+
+    Jim_SetResult(interp, resultObj);
+
+    return JIM_OK;
+}
+
 /* [if] */
 static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -11583,8 +12229,8 @@ static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
     int i;
     int idx;
 
-    if (argc < 3) {
-        Jim_WrongNumArgs(interp, 1, argv, "list index ?...?");
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
         return JIM_ERR;
     }
     objPtr = argv[1];
@@ -11702,13 +12348,12 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
 
     listlen = Jim_ListLength(interp, argv[0]);
     for (i = 0; i < listlen; i++) {
-        Jim_Obj *objPtr;
         int eq = 0;
+        Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i);
 
-        Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE);
         switch (opt_match) {
             case OPT_EXACT:
-                eq = Jim_StringCompareObj(interp, objPtr, argv[1], opt_nocase) == 0;
+                eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0;
                 break;
 
             case OPT_GLOB:
@@ -11816,8 +12461,8 @@ static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
     int idx, len;
     Jim_Obj *listPtr;
 
-    if (argc < 4) {
-        Jim_WrongNumArgs(interp, 1, argv, "list index element " "?element ...?");
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "list index ?element ...?");
         return JIM_ERR;
     }
     listPtr = argv[1];
@@ -11846,11 +12491,9 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
     int first, last, len, rangeLen;
     Jim_Obj *listObj;
     Jim_Obj *newListObj;
-    int i;
-    int shared;
 
     if (argc < 4) {
-        Jim_WrongNumArgs(interp, 1, argv, "list first last ?element element ...?");
+        Jim_WrongNumArgs(interp, 1, argv, "list first last ?element ...?");
         return JIM_ERR;
     }
     if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK ||
@@ -11863,7 +12506,7 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
 
     first = JimRelToAbsIndex(len, first);
     last = JimRelToAbsIndex(len, last);
-    JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
+    JimRelToAbsRange(len, &first, &last, &rangeLen);
 
     /* Now construct a new list which consists of:
      * <elements before first> <supplied elements> <elements after last>
@@ -11883,31 +12526,16 @@ static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
         return JIM_ERR;
     }
 
-    newListObj = Jim_NewListObj(interp, NULL, 0);
-
-    shared = Jim_IsShared(listObj);
-    if (shared) {
-        listObj = Jim_DuplicateObj(interp, listObj);
-    }
-
     /* Add the first set of elements */
-    for (i = 0; i < first; i++) {
-        Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]);
-    }
+    newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first);
 
     /* Add supplied elements */
-    for (i = 4; i < argc; i++) {
-        Jim_ListAppendElement(interp, newListObj, argv[i]);
-    }
+    ListInsertElements(newListObj, -1, argc - 4, argv + 4);
 
     /* Add the remaining elements */
-    for (i = first + rangeLen; i < len; i++) {
-        Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]);
-    }
+    ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen);
+
     Jim_SetResult(interp, newListObj);
-    if (shared) {
-        Jim_FreeNewObj(interp, listObj);
-    }
     return JIM_OK;
 }
 
@@ -11919,25 +12547,23 @@ static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
         return JIM_ERR;
     }
     else if (argc == 3) {
+        /* With no indexes, simply implements [set] */
         if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
             return JIM_ERR;
         Jim_SetResult(interp, argv[2]);
         return JIM_OK;
     }
-    if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1])
-        == JIM_ERR)
-        return JIM_ERR;
-    return JIM_OK;
+    return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]);
 }
 
 /* [lsort] */
 static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[])
 {
     static const char * const options[] = {
-        "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL
+        "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL
     };
     enum
-    { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX };
+    { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE };
     Jim_Obj *resObj;
     int i;
     int retCode;
@@ -11952,13 +12578,14 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
     info.type = JIM_LSORT_ASCII;
     info.order = 1;
     info.indexed = 0;
+    info.unique = 0;
     info.command = NULL;
     info.interp = interp;
 
     for (i = 1; i < (argc - 1); i++) {
         int option;
 
-        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG)
+        if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG)
             != JIM_OK)
             return JIM_ERR;
         switch (option) {
@@ -11971,12 +12598,18 @@ static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const arg
             case OPT_INTEGER:
                 info.type = JIM_LSORT_INTEGER;
                 break;
+            case OPT_REAL:
+                info.type = JIM_LSORT_REAL;
+                break;
             case OPT_INCREASING:
                 info.order = 1;
                 break;
             case OPT_DECREASING:
                 info.order = -1;
                 break;
+            case OPT_UNIQUE:
+                info.unique = 1;
+                break;
             case OPT_COMMAND:
                 if (i >= (argc - 2)) {
                     Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1);
@@ -12173,6 +12806,8 @@ static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
             return JIM_ERR;
         }
         script = Jim_GetScript(interp, argv[2]);
+        if (script == NULL)
+            return JIM_ERR;
         Jim_SetResultInt(interp, script->len);
         return JIM_OK;
     }
@@ -12292,7 +12927,7 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
     if (argc >= 2) {
         int retcode;
         Jim_CallFrame *savedCallFrame, *targetCallFrame;
-        Jim_Obj *objPtr;
+        int savedTailcall;
         const char *str;
 
         /* Save the old callframe pointer */
@@ -12301,7 +12936,7 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
         /* Lookup the target frame pointer */
         str = Jim_String(argv[1]);
         if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
-            targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]);
+            targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
             argc--;
             argv++;
         }
@@ -12312,21 +12947,21 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
             return JIM_ERR;
         }
         if (argc < 2) {
-            argv--;
-            Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
+            Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
             return JIM_ERR;
         }
         /* Eval the code in the target callframe. */
         interp->framePtr = targetCallFrame;
+        /* Can't merge tailcalls across upcall */
+        savedTailcall = interp->framePtr->tailcall;
+        interp->framePtr->tailcall = 0;
         if (argc == 2) {
             retcode = Jim_EvalObj(interp, argv[1]);
         }
         else {
-            objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
-            Jim_IncrRefCount(objPtr);
-            retcode = Jim_EvalObj(interp, objPtr);
-            Jim_DecrRefCount(interp, objPtr);
+            retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
         }
+        interp->framePtr->tailcall = savedTailcall;
         interp->framePtr = savedCallFrame;
         return retcode;
     }
@@ -12429,39 +13064,128 @@ static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
     if (errorCodeObj && returnCode == JIM_ERR) {
         Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj);
     }
-    interp->returnCode = returnCode;
-    interp->returnLevel = level;
+    interp->returnCode = returnCode;
+    interp->returnLevel = level;
+
+    if (i == argc - 1) {
+        Jim_SetResult(interp, argv[i]);
+    }
+    return JIM_RETURN;
+}
+
+/* [tailcall] */
+static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (interp->framePtr->level == 0) {
+        Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1);
+        return JIM_ERR;
+    }
+    else if (argc >= 2) {
+        /* Need to resolve the tailcall command in the current context */
+        Jim_CallFrame *cf = interp->framePtr->parent;
+
+        Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
+        if (cmdPtr == NULL) {
+            return JIM_ERR;
+        }
+
+        JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd"));
+
+        /* And stash this pre-resolved command */
+        JimIncrCmdRefCount(cmdPtr);
+        cf->tailcallCmd = cmdPtr;
+
+        /* And stash the command list */
+        JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj"));
+
+        cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1);
+        Jim_IncrRefCount(cf->tailcallObj);
+
+        /* When the stack unwinds to the previous proc, the stashed command will be evaluated */
+        return JIM_EVAL;
+    }
+    return JIM_OK;
+}
+
+static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *cmdList;
+    Jim_Obj *prefixListObj = Jim_CmdPrivData(interp);
+
+    /* prefixListObj is a list to which the args need to be appended */
+    cmdList = Jim_DuplicateObj(interp, prefixListObj);
+    ListInsertElements(cmdList, -1, argc - 1, argv + 1);
+
+    return JimEvalObjList(interp, cmdList);
+}
+
+static void JimAliasCmdDelete(Jim_Interp *interp, void *privData)
+{
+    Jim_Obj *prefixListObj = privData;
+    Jim_DecrRefCount(interp, prefixListObj);
+}
+
+static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *prefixListObj;
+    const char *newname;
+
+    if (argc < 3) {
+        Jim_WrongNumArgs(interp, 1, argv, "newname command ?args ...?");
+        return JIM_ERR;
+    }
 
-    if (i == argc - 1) {
-        Jim_SetResult(interp, argv[i]);
+    prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2);
+    Jim_IncrRefCount(prefixListObj);
+    newname = Jim_String(argv[1]);
+    if (newname[0] == ':' && newname[1] == ':') {
+        while (*++newname == ':') {
+        }
     }
-    return JIM_RETURN;
-}
 
-/* [tailcall] */
-static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-    Jim_Obj *objPtr;
+    Jim_SetResult(interp, argv[1]);
 
-    objPtr = Jim_NewListObj(interp, argv + 1, argc - 1);
-    Jim_SetResult(interp, objPtr);
-    return JIM_EVAL;
+    return Jim_CreateCommand(interp, newname, JimAliasCmd, prefixListObj, JimAliasCmdDelete);
 }
 
 /* [proc] */
 static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
+    Jim_Cmd *cmd;
+
     if (argc != 4 && argc != 5) {
         Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body");
         return JIM_ERR;
     }
 
+    if (JimValidName(interp, "procedure", argv[1]) != JIM_OK) {
+        return JIM_ERR;
+    }
+
     if (argc == 4) {
-        return JimCreateProcedure(interp, argv[1], argv[2], NULL, argv[3]);
+        cmd = JimCreateProcedureCmd(interp, argv[2], NULL, argv[3], NULL);
     }
     else {
-        return JimCreateProcedure(interp, argv[1], argv[2], argv[3], argv[4]);
+        cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL);
+    }
+
+    if (cmd) {
+        /* Add the new command */
+        Jim_Obj *qualifiedCmdNameObj;
+        const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj);
+
+        JimCreateCommand(interp, cmdname, cmd);
+
+        /* Calculate and set the namespace for this proc */
+        JimUpdateProcNamespace(interp, cmd, cmdname);
+
+        JimFreeQualifiedName(interp, qualifiedCmdNameObj);
+
+        /* Unlike Tcl, set the name of the proc as the result */
+        Jim_SetResult(interp, argv[1]);
+        return JIM_OK;
     }
+    return JIM_ERR;
 }
 
 /* [local] */
@@ -12469,6 +13193,11 @@ static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
 {
     int retcode;
 
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
+        return JIM_ERR;
+    }
+
     /* Evaluate the arguments with 'local' in force */
     interp->local++;
     retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
@@ -12477,17 +13206,17 @@ static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
 
     /* If OK, and the result is a proc, add it to the list of local procs */
     if (retcode == 0) {
-        const char *procname = Jim_String(Jim_GetResult(interp));
+        Jim_Obj *cmdNameObj = Jim_GetResult(interp);
 
-        if (Jim_FindHashEntry(&interp->commands, procname) == NULL) {
-            Jim_SetResultFormatted(interp, "not a proc: \"%s\"", procname);
+        if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) {
             return JIM_ERR;
         }
-        if (interp->localProcs == NULL) {
-            interp->localProcs = Jim_Alloc(sizeof(*interp->localProcs));
-            Jim_InitStack(interp->localProcs);
+        if (interp->framePtr->localCommands == NULL) {
+            interp->framePtr->localCommands = Jim_Alloc(sizeof(*interp->framePtr->localCommands));
+            Jim_InitStack(interp->framePtr->localCommands);
         }
-        Jim_StackPush(interp->localProcs, Jim_StrDup(procname));
+        Jim_IncrRefCount(cmdNameObj);
+        Jim_StackPush(interp->framePtr->localCommands, cmdNameObj);
     }
 
     return retcode;
@@ -12504,8 +13233,8 @@ static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
         int retcode;
 
         Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
-        if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->u.proc.prevCmd) {
-            Jim_SetResultFormatted(interp, "no previous proc: \"%#s\"", argv[1]);
+        if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
+            Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
             return JIM_ERR;
         }
         /* OK. Mark this command as being in an upcall */
@@ -12523,6 +13252,59 @@ static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
     }
 }
 
+/* [apply] */
+static int Jim_ApplyCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+    if (argc < 2) {
+        Jim_WrongNumArgs(interp, 1, argv, "lambdaExpr ?arg ...?");
+        return JIM_ERR;
+    }
+    else {
+        int ret;
+        Jim_Cmd *cmd;
+        Jim_Obj *argListObjPtr;
+        Jim_Obj *bodyObjPtr;
+        Jim_Obj *nsObj = NULL;
+        Jim_Obj **nargv;
+
+        int len = Jim_ListLength(interp, argv[1]);
+        if (len != 2 && len != 3) {
+            Jim_SetResultFormatted(interp, "can't interpret \"%#s\" as a lambda expression", argv[1]);
+            return JIM_ERR;
+        }
+
+        if (len == 3) {
+#ifdef jim_ext_namespace
+            /* Need to canonicalise the given namespace. */
+            nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2));
+#else
+            Jim_SetResultString(interp, "namespaces not enabled", -1);
+            return JIM_ERR;
+#endif
+        }
+        argListObjPtr = Jim_ListGetIndex(interp, argv[1], 0);
+        bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
+
+        cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
+
+        if (cmd) {
+            /* Create a new argv array with a dummy argv[0], for error messages */
+            nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
+            nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
+            Jim_IncrRefCount(nargv[0]);
+            memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
+            ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
+            Jim_DecrRefCount(interp, nargv[0]);
+            Jim_Free(nargv);
+
+            JimDecrCmdRefCount(interp, cmd);
+            return ret;
+        }
+        return JIM_ERR;
+    }
+}
+
+
 /* [concat] */
 static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
@@ -12576,8 +13358,12 @@ static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
     if (interp->framePtr->level == 0)
         return JIM_OK;          /* global at toplevel... */
     for (i = 1; i < argc; i++) {
-        if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
-            return JIM_ERR;
+        /* global ::blah does nothing */
+        const char *name = Jim_String(argv[i]);
+        if (name[0] != ':' || name[1] != ':') {
+            if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK)
+                return JIM_ERR;
+        }
     }
     return JIM_OK;
 }
@@ -12610,25 +13396,19 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
             const char *k;
             int kl;
 
-            Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE);
+            objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i);
             k = Jim_String(objPtr);
             kl = Jim_Utf8Length(interp, objPtr);
 
             if (strLen >= kl && kl) {
                 int rc;
-                if (nocase) {
-                    rc = JimStringCompareNoCase(str, k, kl);
-                }
-                else {
-                    rc = JimStringCompare(str, kl, k, kl);
-                }
+                rc = JimStringCompareLen(str, k, kl, nocase);
                 if (rc == 0) {
                     if (noMatchStart) {
                         Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart);
                         noMatchStart = NULL;
                     }
-                    Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE);
-                    Jim_AppendObj(interp, resultObjPtr, objPtr);
+                    Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1));
                     str += utf8_index(str, kl);
                     strLen -= kl;
                     break;
@@ -12656,19 +13436,22 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
     int opt_case = 1;
     int option;
     static const char * const options[] = {
-        "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "map",
-        "repeat", "reverse", "index", "first", "last",
-        "trim", "trimleft", "trimright", "tolower", "toupper", NULL
+        "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "replace",
+        "map", "repeat", "reverse", "index", "first", "last",
+        "trim", "trimleft", "trimright", "tolower", "toupper", "totitle", NULL
     };
     enum
     {
-        OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_MAP,
-        OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST,
-        OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER
+        OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_REPLACE,
+        OPT_MAP, OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST,
+        OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER, OPT_TOTITLE
     };
     static const char * const nocase_options[] = {
         "-nocase", NULL
     };
+    static const char * const nocase_length_options[] = {
+        "-nocase", "-length", NULL
+    };
 
     if (argc < 2) {
         Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
@@ -12696,23 +13479,54 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
 
         case OPT_COMPARE:
         case OPT_EQUAL:
-            if (argc != 4 &&
-                (argc != 5 ||
-                    Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL,
-                        JIM_ENUM_ABBREV) != JIM_OK)) {
-                Jim_WrongNumArgs(interp, 2, argv, "?-nocase? string1 string2");
-                return JIM_ERR;
-            }
-            if (opt_case == 0) {
-                argv++;
-            }
-            if (option == OPT_COMPARE || !opt_case) {
-                Jim_SetResultInt(interp, Jim_StringCompareObj(interp, argv[2], argv[3], !opt_case));
-            }
-            else {
-                Jim_SetResultBool(interp, Jim_StringEqObj(argv[2], argv[3]));
+            {
+                /* n is the number of remaining option args */
+                long opt_length = -1;
+                int n = argc - 4;
+                int i = 2;
+                while (n > 0) {
+                    int subopt;
+                    if (Jim_GetEnum(interp, argv[i++], nocase_length_options, &subopt, NULL,
+                            JIM_ENUM_ABBREV) != JIM_OK) {
+badcompareargs:
+                        Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2");
+                        return JIM_ERR;
+                    }
+                    if (subopt == 0) {
+                        /* -nocase */
+                        opt_case = 0;
+                        n--;
+                    }
+                    else {
+                        /* -length */
+                        if (n < 2) {
+                            goto badcompareargs;
+                        }
+                        if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) {
+                            return JIM_ERR;
+                        }
+                        n -= 2;
+                    }
+                }
+                if (n) {
+                    goto badcompareargs;
+                }
+                argv += argc - 2;
+                if (opt_length < 0 && option != OPT_COMPARE && opt_case) {
+                    /* Fast version - [string equal], case sensitive, no length */
+                    Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1]));
+                }
+                else {
+                    if (opt_length >= 0) {
+                        n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case);
+                    }
+                    else {
+                        n = Jim_StringCompareObj(interp, argv[0], argv[1], !opt_case);
+                    }
+                    Jim_SetResultInt(interp, option == OPT_COMPARE ? n : n == 0);
+                }
+                return JIM_OK;
             }
-            return JIM_OK;
 
         case OPT_MATCH:
             if (argc != 4 &&
@@ -12773,6 +13587,22 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
                 return JIM_OK;
             }
 
+        case OPT_REPLACE:{
+                Jim_Obj *objPtr;
+
+                if (argc != 5 && argc != 6) {
+                    Jim_WrongNumArgs(interp, 2, argv, "string first last ?string?");
+                    return JIM_ERR;
+                }
+                objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL);
+                if (objPtr == NULL) {
+                    return JIM_ERR;
+                }
+                Jim_SetResult(interp, objPtr);
+                return JIM_OK;
+            }
+
+
         case OPT_REPEAT:{
                 Jim_Obj *objPtr;
                 jim_wide count;
@@ -12911,6 +13741,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
 
         case OPT_TOLOWER:
         case OPT_TOUPPER:
+        case OPT_TOTITLE:
             if (argc != 3) {
                 Jim_WrongNumArgs(interp, 2, argv, "string");
                 return JIM_ERR;
@@ -12918,9 +13749,12 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
             if (option == OPT_TOLOWER) {
                 Jim_SetResult(interp, JimStringToLower(interp, argv[2]));
             }
-            else {
+            else if (option == OPT_TOUPPER) {
                 Jim_SetResult(interp, JimStringToUpper(interp, argv[2]));
             }
+            else {
+                Jim_SetResult(interp, JimStringToTitle(interp, argv[2]));
+            }
             return JIM_OK;
 
         case OPT_IS:
@@ -13055,17 +13889,19 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
     }
 
     interp->signal_level += sig;
-    if (interp->signal_level && interp->sigmask) {
+    if (Jim_CheckSignal(interp)) {
         /* If a signal is set, don't even try to execute the body */
         exitCode = JIM_SIGNAL;
     }
     else {
         exitCode = Jim_EvalObj(interp, argv[0]);
+        /* Don't want any caught error included in a later stack trace */
+        interp->errorFlag = 0;
     }
     interp->signal_level -= sig;
 
     /* Catch or pass through? Only the first 32/64 codes can be passed through */
-    if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) {
+    if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) {
         /* Not caught, pass it up */
         return exitCode;
     }
@@ -13211,21 +14047,20 @@ static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
 static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     Jim_Obj *listObjPtr;
-    Jim_HashTableIterator *htiter;
+    Jim_HashTableIterator htiter;
     Jim_HashEntry *he;
 
     listObjPtr = Jim_NewListObj(interp, NULL, 0);
 
-    htiter = Jim_GetHashTableIterator(&interp->references);
-    while ((he = Jim_NextHashEntry(htiter)) != NULL) {
-        char buf[JIM_REFERENCE_SPACE];
-        Jim_Reference *refPtr = he->u.val;
-        const jim_wide *refId = he->key;
+    JimInitHashTableIterator(&interp->references, &htiter);
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        char buf[JIM_REFERENCE_SPACE + 1];
+        Jim_Reference *refPtr = Jim_GetHashEntryVal(he);
+        const unsigned long *refId = he->key;
 
         JimFormatReference(buf, refPtr, *refId);
         Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
     }
-    Jim_FreeHashTableIterator(htiter);
     Jim_SetResult(interp, listObjPtr);
     return JIM_OK;
 }
@@ -13234,8 +14069,6 @@ static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 /* [rename] */
 static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-    const char *oldName, *newName;
-
     if (argc != 3) {
         Jim_WrongNumArgs(interp, 1, argv, "oldName newName");
         return JIM_ERR;
@@ -13245,41 +14078,58 @@ static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
         return JIM_ERR;
     }
 
-    oldName = Jim_String(argv[1]);
-    newName = Jim_String(argv[2]);
-    return Jim_RenameCommand(interp, oldName, newName);
+    return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2]));
 }
 
-int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj)
-{
-    int i;
-    int len;
-    Jim_Obj *resultObj;
-    Jim_Obj *dictObj;
-    Jim_Obj **dictValuesObj;
+#define JIM_DICTMATCH_VALUES 0x0001
 
-    if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) {
-        return JIM_ERR;
-    }
+typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type);
 
-    /* XXX: Could make the exact-match case much more efficient here.
-     *      See JimCommandsList()
-     */
-    if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) {
-        return JIM_ERR;
+static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type)
+{
+    Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key);
+    if (type & JIM_DICTMATCH_VALUES) {
+        Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he));
     }
+}
 
-    /* Only return the matching values */
-    resultObj = Jim_NewListObj(interp, NULL, 0);
+/**
+ * Like JimHashtablePatternMatch, but for dictionaries.
+ */
+static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr,
+    JimDictMatchCallbackType *callback, int type)
+{
+    Jim_HashEntry *he;
+    Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
 
-    for (i = 0; i < len; i += 2) {
-        if (patternObj == NULL || Jim_StringMatchObj(interp, patternObj, dictValuesObj[i], 0)) {
-            Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]);
+    /* Check for the non-pattern case. We can do this much more efficiently. */
+    Jim_HashTableIterator htiter;
+    JimInitHashTableIterator(ht, &htiter);
+    while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
+        if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
+            callback(interp, listObjPtr, he, type);
         }
     }
-    Jim_Free(dictValuesObj);
 
-    Jim_SetResult(interp, resultObj);
+    return listObjPtr;
+}
+
+
+int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
+{
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0));
+    return JIM_OK;
+}
+
+int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr)
+{
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+    Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES));
     return JIM_OK;
 }
 
@@ -13291,17 +14141,61 @@ int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr)
     return ((Jim_HashTable *)objPtr->internalRep.ptr)->used;
 }
 
+int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+    Jim_HashTable *ht;
+    unsigned int i;
+
+    if (SetDictFromAny(interp, objPtr) != JIM_OK) {
+        return JIM_ERR;
+    }
+
+    ht = (Jim_HashTable *)objPtr->internalRep.ptr;
+
+    /* Note that this uses internal knowledge of the hash table */
+    printf("%d entries in table, %d buckets\n", ht->used, ht->size);
+
+    for (i = 0; i < ht->size; i++) {
+        Jim_HashEntry *he = ht->table[i];
+
+        if (he) {
+            printf("%d: ", i);
+
+            while (he) {
+                printf(" %s", Jim_String(he->key));
+                he = he->next;
+            }
+            printf("\n");
+        }
+    }
+    return JIM_OK;
+}
+
+static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv)
+{
+    Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1);
+
+    Jim_AppendString(interp, prefixObj, " ", 1);
+    Jim_AppendString(interp, prefixObj, subcmd, -1);
+
+    return Jim_EvalObjPrefix(interp, prefixObj, argc, argv);
+}
+
 /* [dict] */
 static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     Jim_Obj *objPtr;
     int option;
     static const char * const options[] = {
-        "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL
+        "create", "get", "set", "unset", "exists", "keys", "size", "info",
+        "merge", "with", "append", "lappend", "incr", "remove", "values", "for",
+        "replace", "update", NULL
     };
     enum
     {
-        OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH,
+        OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO,
+        OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR,
+        OPT_REPLACE, OPT_UPDATE,
     };
 
     if (argc < 2) {
@@ -13316,7 +14210,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
     switch (option) {
         case OPT_GET:
             if (argc < 3) {
-                Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
+                Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?");
                 return JIM_ERR;
             }
             if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr,
@@ -13333,67 +14227,64 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
             }
             return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
 
-        case OPT_EXIST:
-            if (argc < 3) {
-                Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?");
+        case OPT_EXISTS:
+            if (argc < 4) {
+                Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?");
                 return JIM_ERR;
             }
-            Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3,
-                    &objPtr, JIM_ERRMSG) == JIM_OK);
-            return JIM_OK;
+            else {
+                int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG);
+                if (rc < 0) {
+                    return JIM_ERR;
+                }
+                Jim_SetResultBool(interp,  rc == JIM_OK);
+                return JIM_OK;
+            }
 
         case OPT_UNSET:
             if (argc < 4) {
                 Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?");
                 return JIM_ERR;
             }
-            return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE);
+            if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) {
+                return JIM_ERR;
+            }
+            return JIM_OK;
 
         case OPT_KEYS:
             if (argc != 3 && argc != 4) {
-                Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?");
+                Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?");
                 return JIM_ERR;
             }
             return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL);
 
-        case OPT_SIZE: {
-            int size;
-
+        case OPT_SIZE:
             if (argc != 3) {
-                Jim_WrongNumArgs(interp, 2, argv, "dictVar");
+                Jim_WrongNumArgs(interp, 2, argv, "dictionary");
                 return JIM_ERR;
             }
-
-            size = Jim_DictSize(interp, argv[2]);
-            if (size < 0) {
+            else if (Jim_DictSize(interp, argv[2]) < 0) {
                 return JIM_ERR;
             }
-            Jim_SetResultInt(interp, size);
+            Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2]));
             return JIM_OK;
-        }
 
         case OPT_MERGE:
             if (argc == 2) {
                 return JIM_OK;
             }
-            else if (argv[2]->typePtr != &dictObjType && SetDictFromAny(interp, argv[2]) != JIM_OK) {
+            if (Jim_DictSize(interp, argv[2]) < 0) {
                 return JIM_ERR;
             }
-            else {
-                return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2);
-            }
+            /* Handle as ensemble */
+            break;
 
-        case OPT_WITH:
-            if (argc < 4) {
-                Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script");
-                return JIM_ERR;
-            }
-            else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) {
-                return JIM_ERR;
-            }
-            else {
-                return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2);
+        case OPT_UPDATE:
+            if (argc < 6 || argc % 2) {
+                /* Better error message */
+                argc = 2;
             }
+            break;
 
         case OPT_CREATE:
             if (argc % 2) {
@@ -13404,9 +14295,15 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
             Jim_SetResult(interp, objPtr);
             return JIM_OK;
 
-        default:
-            abort();
+        case OPT_INFO:
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "dictionary");
+                return JIM_ERR;
+            }
+            return Jim_DictInfo(interp, argv[2]);
     }
+    /* Handle command as an ensemble */
+    return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2);
 }
 
 /* [subst] */
@@ -13459,18 +14356,29 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
     int mode = 0;
 
     static const char * const commands[] = {
-        "body", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals",
+        "body", "statics", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals",
         "vars", "version", "patchlevel", "complete", "args", "hostname",
         "script", "source", "stacktrace", "nameofexecutable", "returncodes",
-        "references", NULL
+        "references", "alias", NULL
     };
     enum
-    { INFO_BODY, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
+    { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL,
         INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS,
         INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE,
-        INFO_RETURNCODES, INFO_REFERENCES,
+        INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS,
     };
 
+#ifdef jim_ext_namespace
+    int nons = 0;
+
+    if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) {
+        /* This is for internal use only */
+        argc--;
+        argv++;
+        nons = 1;
+    }
+#endif
+
     if (argc < 2) {
         Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?");
         return JIM_ERR;
@@ -13482,28 +14390,54 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
 
     /* Test for the the most common commands first, just in case it makes a difference */
     switch (cmd) {
-        case INFO_EXISTS:{
-                if (argc != 3) {
-                    Jim_WrongNumArgs(interp, 2, argv, "varName");
-                    return JIM_ERR;
-                }
-                Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL);
-                break;
+        case INFO_EXISTS:
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "varName");
+                return JIM_ERR;
+            }
+            Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL);
+            break;
+
+        case INFO_ALIAS:{
+            Jim_Cmd *cmdPtr;
+
+            if (argc != 3) {
+                Jim_WrongNumArgs(interp, 2, argv, "command");
+                return JIM_ERR;
+            }
+            if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) {
+                return JIM_ERR;
+            }
+            if (cmdPtr->isproc || cmdPtr->u.native.cmdProc != JimAliasCmd) {
+                Jim_SetResultFormatted(interp, "command \"%#s\" is not an alias", argv[2]);
+                return JIM_ERR;
             }
+            Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData);
+            return JIM_OK;
+        }
 
         case INFO_CHANNELS:
+            mode++;             /* JIM_CMDLIST_CHANNELS */
 #ifndef jim_ext_aio
             Jim_SetResultString(interp, "aio not enabled", -1);
             return JIM_ERR;
 #endif
-        case INFO_COMMANDS:
         case INFO_PROCS:
+            mode++;             /* JIM_CMDLIST_PROCS */
+        case INFO_COMMANDS:
+            /* mode 0 => JIM_CMDLIST_COMMANDS */
             if (argc != 2 && argc != 3) {
                 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
                 return JIM_ERR;
             }
-            Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL,
-                    (cmd - INFO_COMMANDS)));
+#ifdef jim_ext_namespace
+            if (!nons) {
+                if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+                    return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
+                }
+            }
+#endif
+            Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
             break;
 
         case INFO_VARS:
@@ -13516,6 +14450,13 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
                 Jim_WrongNumArgs(interp, 2, argv, "?pattern?");
                 return JIM_ERR;
             }
+#ifdef jim_ext_namespace
+            if (!nons) {
+                if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) {
+                    return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
+                }
+            }
+#endif
             Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode));
             break;
 
@@ -13543,7 +14484,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
                 else if (argv[2]->typePtr == &scriptObjType) {
                     ScriptObj *script = Jim_GetScript(interp, argv[2]);
                     fileNameObj = script->fileNameObj;
-                    line = script->line;
+                    line = script->firstline;
                 }
                 else {
                     fileNameObj = interp->emptyObj;
@@ -13581,6 +14522,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
             break;
 
         case INFO_BODY:
+        case INFO_STATICS:
         case INFO_ARGS:{
                 Jim_Cmd *cmdPtr;
 
@@ -13595,8 +14537,21 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
                     Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]);
                     return JIM_ERR;
                 }
-                Jim_SetResult(interp,
-                    cmd == INFO_BODY ? cmdPtr->u.proc.bodyObjPtr : cmdPtr->u.proc.argListObjPtr);
+                switch (cmd) {
+                    case INFO_BODY:
+                        Jim_SetResult(interp, cmdPtr->u.proc.bodyObjPtr);
+                        break;
+                    case INFO_ARGS:
+                        Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr);
+                        break;
+                    case INFO_STATICS:
+                        if (cmdPtr->u.proc.staticVars) {
+                            int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES;
+                            Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars,
+                                NULL, JimVariablesMatch, mode));
+                        }
+                        break;
+                }
                 break;
             }
 
@@ -13682,13 +14637,14 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
 static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     Jim_Obj *objPtr;
+    int result = 0;
 
     static const char * const options[] = {
-        "-command", "-proc", "-var", NULL
+        "-command", "-proc", "-alias", "-var", NULL
     };
     enum
     {
-        OPT_COMMAND, OPT_PROC, OPT_VAR
+        OPT_COMMAND, OPT_PROC, OPT_ALIAS, OPT_VAR
     };
     int option;
 
@@ -13707,19 +14663,30 @@ static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
         return JIM_ERR;
     }
 
-    /* Test for the the most common commands first, just in case it makes a difference */
-    switch (option) {
-        case OPT_VAR:
-            Jim_SetResultBool(interp, Jim_GetVariable(interp, objPtr, 0) != NULL);
-            break;
+    if (option == OPT_VAR) {
+        result = Jim_GetVariable(interp, objPtr, 0) != NULL;
+    }
+    else {
+        /* Now different kinds of commands */
+        Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
 
-        case OPT_COMMAND:
-        case OPT_PROC: {
-            Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE);
-            Jim_SetResultBool(interp, cmd != NULL && (option == OPT_COMMAND || cmd->isproc));
-            break;
+        if (cmd) {
+            switch (option) {
+            case OPT_COMMAND:
+                result = 1;
+                break;
+
+            case OPT_ALIAS:
+                result = cmd->isproc == 0 && cmd->u.native.cmdProc == JimAliasCmd;
+                break;
+
+            case OPT_PROC:
+                result = cmd->isproc;
+                break;
+            }
         }
     }
+    Jim_SetResultBool(interp, result);
     return JIM_OK;
 }
 
@@ -13816,8 +14783,7 @@ static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
 static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
     const char *joinStr;
-    int joinStrLen, i, listLen;
-    Jim_Obj *resObjPtr;
+    int joinStrLen;
 
     if (argc != 2 && argc != 3) {
         Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
@@ -13831,19 +14797,7 @@ static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
     else {
         joinStr = Jim_GetString(argv[2], &joinStrLen);
     }
-    listLen = Jim_ListLength(interp, argv[1]);
-    resObjPtr = Jim_NewStringObj(interp, NULL, 0);
-    /* Split */
-    for (i = 0; i < listLen; i++) {
-        Jim_Obj *objPtr = 0;
-
-        Jim_ListIndex(interp, argv[1], i, &objPtr, JIM_NONE);
-        Jim_AppendObj(interp, resObjPtr, objPtr);
-        if (i + 1 != listLen) {
-            Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen);
-        }
-    }
-    Jim_SetResult(interp, resObjPtr);
+    Jim_SetResult(interp, Jim_ListJoin(interp, argv[1], joinStr, joinStrLen));
     return JIM_OK;
 }
 
@@ -13990,11 +14944,7 @@ static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
 
     objPtr = Jim_NewListObj(interp, argv, argc);
     while (--count) {
-        int i;
-
-        for (i = 0; i < argc; i++) {
-            ListAppendElement(objPtr, argv[i]);
-        }
+        ListInsertElements(objPtr, -1, argc, argv);
     }
 
     Jim_SetResult(interp, objPtr);
@@ -14201,8 +15151,9 @@ static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
 
 static const struct {
     const char *name;
-    Jim_CmdProc cmdProc;
+    Jim_CmdProc *cmdProc;
 } Jim_CoreCommandsTable[] = {
+    {"alias", Jim_AliasCoreCommand},
     {"set", Jim_SetCoreCommand},
     {"unset", Jim_UnsetCoreCommand},
     {"puts", Jim_PutsCoreCommand},
@@ -14216,6 +15167,7 @@ static const struct {
     {"for", Jim_ForCoreCommand},
     {"foreach", Jim_ForeachCoreCommand},
     {"lmap", Jim_LmapCoreCommand},
+    {"lassign", Jim_LassignCoreCommand},
     {"if", Jim_IfCoreCommand},
     {"switch", Jim_SwitchCoreCommand},
     {"list", Jim_ListCoreCommand},
@@ -14270,6 +15222,7 @@ static const struct {
     {"tailcall", Jim_TailcallCoreCommand},
     {"local", Jim_LocalCoreCommand},
     {"upcall", Jim_UpcallCoreCommand},
+    {"apply", Jim_ApplyCoreCommand},
     {NULL, NULL},
 };
 
@@ -14451,6 +15404,8 @@ void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...)
     buf = Jim_Alloc(len + 1);
     len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]);
 
+    va_end(args);
+
     Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len));
 }
 
index fdc9db9..ece4b74 100644 (file)
--- a/jim/jim.h
+++ b/jim/jim.h
@@ -3,7 +3,7 @@
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
  * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
- * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
+ * Copyright 2008 oharboe - Ã˜yvind Harboe - oyvind.harboe@zylin.com
  * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
  * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
  * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
@@ -125,11 +125,6 @@ extern "C" {
  * Exported defines
  * ---------------------------------------------------------------------------*/
 
-/* Jim version numbering: every version of jim is marked with a
- * successive integer number. This is version 0. The first
- * stable version will be 1, then 2, 3, and so on. */
-#define JIM_VERSION 72
-
 #define JIM_OK 0
 #define JIM_ERR 1
 #define JIM_RETURN 2
@@ -140,14 +135,22 @@ extern "C" {
 /* The following are internal codes and should never been seen/used */
 #define JIM_EVAL 7
 
-#define JIM_MAX_NESTING_DEPTH 1000 /* default max nesting depth */
+#define JIM_MAX_CALLFRAME_DEPTH 1000 /* default max nesting depth for procs */
+#define JIM_MAX_EVAL_DEPTH 2000 /* default max nesting depth for eval */
 
 /* Some function get an integer argument with flags to change
  * the behaviour. */
-#define JIM_NONE 0    /* no flags set */
-#define JIM_ERRMSG 1    /* set an error message in the interpreter. */
 
-#define JIM_UNSHARED 4 /* Flag to Jim_GetVariable() */
+/* Starting from 1 << 20 flags are reserved for private uses of
+ * different calls. This way the same 'flags' argument may be used
+ * to pass both global flags and private flags. */
+#define JIM_PRIV_FLAG_SHIFT 20
+
+#define JIM_NONE 0              /* no flags set */
+#define JIM_ERRMSG 1            /* set an error message in the interpreter. */
+#define JIM_ENUM_ABBREV 2       /* Jim_GetEnum() - Allow unambiguous abbreviation */
+#define JIM_UNSHARED 4          /* Jim_GetVariable() - return unshared object */
+#define JIM_MUSTEXIST 8         /* Jim_SetDictKeysVector() - fail if non-existent */
 
 /* Flags for Jim_SubstObj() */
 #define JIM_SUBST_NOVAR 1 /* don't perform variables substitutions */
@@ -155,12 +158,6 @@ extern "C" {
 #define JIM_SUBST_NOESC 4 /* don't perform escapes substitutions */
 #define JIM_SUBST_FLAG 128 /* flag to indicate that this is a real substition object */
 
-/* Unused arguments generate annoying warnings... */
-#define JIM_NOTUSED(V) ((void) V)
-
-/* Flags for Jim_GetEnum() */
-#define JIM_ENUM_ABBREV 2    /* Allow unambiguous abbreviation */
-
 /* Flags used by API calls getting a 'nocase' argument. */
 #define JIM_CASESENS    0   /* case sensitive */
 #define JIM_NOCASE      1   /* no case */
@@ -168,12 +165,8 @@ extern "C" {
 /* Filesystem related */
 #define JIM_PATH_LEN 1024
 
-/* Newline, some embedded system may need -DJIM_CRLF */
-#ifdef JIM_CRLF
-#define JIM_NL "\r\n"
-#else
-#define JIM_NL "\n"
-#endif
+/* Unused arguments generate annoying warnings... */
+#define JIM_NOTUSED(V) ((void) V)
 
 #define JIM_LIBPATH "auto_path"
 #define JIM_INTERACTIVE "tcl_interactive"
@@ -193,7 +186,7 @@ typedef struct Jim_Stack {
  * ---------------------------------------------------------------------------*/
 
 typedef struct Jim_HashEntry {
-    const void *key;
+    void *key;
     union {
         void *val;
         int intval;
@@ -203,27 +196,28 @@ typedef struct Jim_HashEntry {
 
 typedef struct Jim_HashTableType {
     unsigned int (*hashFunction)(const void *key);
-    const void *(*keyDup)(void *privdata, const void *key);
+    void *(*keyDup)(void *privdata, const void *key);
     void *(*valDup)(void *privdata, const void *obj);
     int (*keyCompare)(void *privdata, const void *key1, const void *key2);
-    void (*keyDestructor)(void *privdata, const void *key);
+    void (*keyDestructor)(void *privdata, void *key);
     void (*valDestructor)(void *privdata, void *obj);
 } Jim_HashTableType;
 
 typedef struct Jim_HashTable {
     Jim_HashEntry **table;
     const Jim_HashTableType *type;
+    void *privdata;
     unsigned int size;
     unsigned int sizemask;
     unsigned int used;
     unsigned int collisions;
-    void *privdata;
+    unsigned int uniq;
 } Jim_HashTable;
 
 typedef struct Jim_HashTableIterator {
     Jim_HashTable *ht;
-    int index;
     Jim_HashEntry *entry, *nextEntry;
+    int index;
 } Jim_HashTableIterator;
 
 /* This is the initial size of every hash table */
@@ -236,9 +230,9 @@ typedef struct Jim_HashTableIterator {
 
 #define Jim_SetHashVal(ht, entry, _val_) do { \
     if ((ht)->type->valDup) \
-        entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \
+        (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \
     else \
-        entry->u.val = (_val_); \
+        (entry)->u.val = (_val_); \
 } while(0)
 
 #define Jim_FreeEntryKey(ht, entry) \
@@ -247,20 +241,20 @@ typedef struct Jim_HashTableIterator {
 
 #define Jim_SetHashKey(ht, entry, _key_) do { \
     if ((ht)->type->keyDup) \
-        entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
+        (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \
     else \
-        entry->key = (_key_); \
+        (entry)->key = (void *)(_key_); \
 } while(0)
 
 #define Jim_CompareHashKeys(ht, key1, key2) \
     (((ht)->type->keyCompare) ? \
-        (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
+        (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \
         (key1) == (key2))
 
-#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key)
+#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq)
 
 #define Jim_GetHashEntryKey(he) ((he)->key)
-#define Jim_GetHashEntryVal(he) ((he)->val)
+#define Jim_GetHashEntryVal(he) ((he)->u.val)
 #define Jim_GetHashTableCollisions(ht) ((ht)->collisions)
 #define Jim_GetHashTableSize(ht) ((ht)->size)
 #define Jim_GetHashTableUsed(ht) ((ht)->used)
@@ -280,20 +274,16 @@ typedef struct Jim_HashTableIterator {
  * The refcount of a freed object is always -1.
  * ---------------------------------------------------------------------------*/
 typedef struct Jim_Obj {
-    int refCount; /* reference count */
     char *bytes; /* string representation buffer. NULL = no string repr. */
-    int length; /* number of bytes in 'bytes', not including the numterm. */
     const struct Jim_ObjType *typePtr; /* object type. */
+    int refCount; /* reference count */
+    int length; /* number of bytes in 'bytes', not including the null term. */
     /* Internal representation union */
     union {
         /* integer number type */
         jim_wide wideValue;
-        /* hashed object type value */
-        int hashValue;
-        /* index type */
-        int indexValue;
-        /* return code type */
-        int returnCode;
+        /* generic integer value (e.g. index, return code) */
+        int intValue;
         /* double number type */
         double doubleValue;
         /* Generic pointer */
@@ -305,13 +295,15 @@ typedef struct Jim_Obj {
         } twoPtrValue;
         /* Variable object */
         struct {
-            unsigned jim_wide callFrameId;
             struct Jim_Var *varPtr;
+            unsigned long callFrameId; /* for caching */
+            int global; /* If the variable name is globally scoped with :: */
         } varValue;
         /* Command object */
         struct {
-            unsigned jim_wide procEpoch;
+            struct Jim_Obj *nsObj;
             struct Jim_Cmd *cmdPtr;
+            unsigned long procEpoch; /* for caching */
         } cmdValue;
         /* List object */
         struct {
@@ -326,7 +318,7 @@ typedef struct Jim_Obj {
         } strValue;
         /* Reference type */
         struct {
-            jim_wide id;
+            unsigned long id;
             struct Jim_Reference *refPtr;
         } refValue;
         /* Source type */
@@ -339,15 +331,10 @@ typedef struct Jim_Obj {
             struct Jim_Obj *varNameObjPtr;
             struct Jim_Obj *indexObjPtr;
         } dictSubstValue;
-        /* tagged binary type */
-        struct {
-            unsigned char *data;
-            size_t         len;
-        } binaryValue;
         /* Regular expression pattern */
         struct {
-            unsigned flags;
             void *compre;       /* really an allocated (regex_t *) */
+            unsigned flags;
         } regexpValue;
         struct {
             int line;
@@ -391,17 +378,18 @@ typedef struct Jim_Obj {
     (o)->internalRep.ptr = (p)
 
 /* The object type structure.
- * There are four methods.
+ * There are three methods.
  *
- * - FreeIntRep is used to free the internal representation of the object.
+ * - freeIntRepProc is used to free the internal representation of the object.
  *   Can be NULL if there is nothing to free.
- * - DupIntRep is used to duplicate the internal representation of the object.
+ *
+ * - dupIntRepProc is used to duplicate the internal representation of the object.
  *   If NULL, when an object is duplicated, the internalRep union is
  *   directly copied from an object to another.
  *   Note that it's up to the caller to free the old internal repr of the
  *   object before to call the Dup method.
- * - UpdateString is used to create the string from the internal repr.
- * - setFromAny is used to convert the current object into one of this type.
+ *
+ * - updateStringProc is used to create the string from the internal repr.
  */
 
 struct Jim_Interp;
@@ -435,18 +423,23 @@ typedef struct Jim_ObjType {
 
 /* Call frame */
 typedef struct Jim_CallFrame {
-    unsigned jim_wide id; /* Call Frame ID. Used for caching. */
+    unsigned long id; /* Call Frame ID. Used for caching. */
     int level; /* Level of this call frame. 0 = global */
     struct Jim_HashTable vars; /* Where local vars are stored */
     struct Jim_HashTable *staticVars; /* pointer to procedure static vars */
-    struct Jim_CallFrame *parentCallFrame;
+    struct Jim_CallFrame *parent; /* The parent callframe */
     Jim_Obj *const *argv; /* object vector of the current procedure call. */
     int argc; /* number of args of the current procedure call. */
     Jim_Obj *procArgsObjPtr; /* arglist object of the running procedure */
     Jim_Obj *procBodyObjPtr; /* body object of the running procedure */
-    struct Jim_CallFrame *nextFramePtr;
+    struct Jim_CallFrame *next; /* Callframes are in a linked list */
+    Jim_Obj *nsObj;             /* Namespace for this proc call frame */
     Jim_Obj *fileNameObj;       /* file and line of caller of this proc (if available) */
     int line;
+    Jim_Stack *localCommands; /* commands to be destroyed when the call frame is destroyed */
+    int tailcall;            /* non-zero if a tailcall is being evaluated at this level */
+    struct Jim_Obj *tailcallObj;  /* Pending tailcall invocation */
+    struct Jim_Cmd *tailcallCmd;  /* Resolved command for pending tailcall invocation */
 } Jim_CallFrame;
 
 /* The var structure. It just holds the pointer of the referenced
@@ -462,23 +455,24 @@ typedef struct Jim_Var {
 } Jim_Var;
 
 /* The cmd structure. */
-typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc,
+typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc,
     Jim_Obj *const *argv);
-typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData);
+typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData);
 
 
 
-/* A command is implemented in C if funcPtr is != NULL, otherwise
+/* A command is implemented in C if isproc is 0, otherwise
  * it's a Tcl procedure with the arglist and body represented by the
  * two objects referenced by arglistObjPtr and bodyoObjPtr. */
 typedef struct Jim_Cmd {
     int inUse;           /* Reference count */
     int isproc;          /* Is this a procedure? */
+    struct Jim_Cmd *prevCmd;    /* Previous command defn if cmd created 'local' */
     union {
         struct {
             /* native (C) command */
-            Jim_CmdProc cmdProc; /* The command implementation */
-            Jim_DelCmdProc delProc; /* Called when the command is deleted if != NULL */
+            Jim_CmdProc *cmdProc; /* The command implementation */
+            Jim_DelCmdProc *delProc; /* Called when the command is deleted if != NULL */
             void *privData; /* command-private data available via Jim_CmdPrivData() */
         } native;
         struct {
@@ -486,7 +480,6 @@ typedef struct Jim_Cmd {
             Jim_Obj *argListObjPtr;
             Jim_Obj *bodyObjPtr;
             Jim_HashTable *staticVars;  /* Static vars hash table. NULL if no statics. */
-            struct Jim_Cmd *prevCmd;    /* Previous command defn if proc created 'local' */
             int argListLen;             /* Length of argListObjPtr */
             int reqArity;               /* Number of required parameters */
             int optArity;               /* Number of optional parameters */
@@ -496,6 +489,7 @@ typedef struct Jim_Cmd {
                 Jim_Obj *nameObjPtr;    /* Name of this arg */
                 Jim_Obj *defaultObjPtr; /* Default value, (or rename for $args) */
             } *arglist;
+            Jim_Obj *nsObj;             /* Namespace for this proc */
         } proc;
     } u;
 } Jim_Cmd;
@@ -515,7 +509,9 @@ typedef struct Jim_Interp {
     int errorLine; /* Error line where an error occurred. */
     Jim_Obj *errorFileNameObj; /* Error file where an error occurred. */
     int addStackTrace; /* > 0 If a level should be added to the stack trace */
-    int maxNestingDepth; /* Used for infinite loop detection. */
+    int maxCallFrameDepth; /* Used for infinite loop detection. */
+    int maxEvalDepth; /* Used for infinite loop detection. */
+    int evalDepth;  /* Current eval depth */
     int returnCode; /* Completion code to return on JIM_RETURN. */
     int returnLevel; /* Current level of 'return -level' */
     int exitCode; /* Code to return to the OS on JIM_EXIT. */
@@ -526,10 +522,10 @@ typedef struct Jim_Interp {
     Jim_CallFrame *framePtr; /* Pointer to the current call frame */
     Jim_CallFrame *topFramePtr; /* toplevel/global frame pointer. */
     struct Jim_HashTable commands; /* Commands hash table */
-    unsigned jim_wide procEpoch; /* Incremented every time the result
+    unsigned long procEpoch; /* Incremented every time the result
                 of procedures names lookup caching
                 may no longer be valid. */
-    unsigned jim_wide callFrameEpoch; /* Incremented every time a new
+    unsigned long callFrameEpoch; /* Incremented every time a new
                 callframe is created. This id is used for the
                 'ID' field contained in the Jim_CallFrame
                 structure. */
@@ -537,12 +533,13 @@ typedef struct Jim_Interp {
     Jim_Obj *liveList; /* Linked list of all the live objects. */
     Jim_Obj *freeList; /* Linked list of all the unused objects. */
     Jim_Obj *currentScriptObj; /* Script currently in execution. */
+    Jim_Obj *nullScriptObj; /* script representation of an empty string */
     Jim_Obj *emptyObj; /* Shared empty string object. */
     Jim_Obj *trueObj; /* Shared true int object. */
     Jim_Obj *falseObj; /* Shared false int object. */
-    unsigned jim_wide referenceNextId; /* Next id for reference. */
+    unsigned long referenceNextId; /* Next id for reference. */
     struct Jim_HashTable references; /* References hash table. */
-    jim_wide lastCollectId; /* reference max Id of the last GC
+    unsigned long lastCollectId; /* reference max Id of the last GC
                 execution. It's set to -1 while the collection
                 is running as sentinel to avoid to recursive
                 calls via the [collect] command inside
@@ -561,7 +558,6 @@ typedef struct Jim_Interp {
     struct Jim_HashTable assocData; /* per-interp storage for use by packages */
     Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */
     struct Jim_HashTable packages; /* Provided packages hash table */
-    Jim_Stack *localProcs; /* procs to be destroyed on end of evaluation */
     Jim_Stack *loadHandles; /* handles of loaded modules [load] */
 } Jim_Interp;
 
@@ -577,7 +573,6 @@ typedef struct Jim_Interp {
 #define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj)
 #define Jim_GetResult(i) ((i)->result)
 #define Jim_CmdPrivData(i) ((i)->cmdPrivData)
-#define Jim_String(o) Jim_GetString((o), NULL)
 
 /* Note that 'o' is expanded only one time inside this macro,
  * so it's safe to use side effects. */
@@ -604,20 +599,7 @@ typedef struct Jim_Reference {
  * Exported API prototypes.
  * ---------------------------------------------------------------------------*/
 
-/* Macros that are common for extensions and core. */
 #define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0)
-
-/* The core includes real prototypes, extensions instead
- * include a global function pointer for every function exported.
- * Once the extension calls Jim_InitExtension(), the global
- * functon pointers are set to the value of the STUB table
- * contained in the Jim_Interp structure.
- *
- * This makes Jim able to load extensions even if it is statically
- * linked itself, and to load extensions compiled with different
- * versions of Jim (as long as the API is still compatible.) */
-
-/* Macros are common for core and extensions */
 #define Jim_FreeHashTableIterator(iter) Jim_Free(iter)
 
 #define JIM_EXPORT
@@ -632,6 +614,7 @@ JIM_EXPORT char *Jim_StrDupLen(const char *s, int l);
 /* environment */
 JIM_EXPORT char **Jim_GetEnviron(void);
 JIM_EXPORT void Jim_SetEnviron(char **env);
+JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template);
 
 /* evaluation */
 JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script);
@@ -647,9 +630,11 @@ JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename);
 JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr);
 JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc,
         Jim_Obj *const *objv);
+JIM_EXPORT int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listObj);
 JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix,
         int objc, Jim_Obj *const *objv);
 #define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov))
+JIM_EXPORT int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj);
 JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr,
         Jim_Obj **resObjPtrPtr, int flags);
 
@@ -665,7 +650,7 @@ JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *p
 /* hash table */
 JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht,
         const Jim_HashTableType *type, void *privdata);
-JIM_EXPORT int Jim_ExpandHashTable (Jim_HashTable *ht,
+JIM_EXPORT void Jim_ExpandHashTable (Jim_HashTable *ht,
         unsigned int size);
 JIM_EXPORT int Jim_AddHashEntry (Jim_HashTable *ht, const void *key,
         void *val);
@@ -676,7 +661,7 @@ JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht,
 JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht);
 JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht,
         const void *key);
-JIM_EXPORT int Jim_ResizeHashTable (Jim_HashTable *ht);
+JIM_EXPORT void Jim_ResizeHashTable (Jim_HashTable *ht);
 JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator
         (Jim_HashTable *ht);
 JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry
@@ -686,12 +671,11 @@ JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry
 JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
 JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
 JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
-JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes,
-        int length);
 JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
         Jim_Obj *objPtr);
 JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
         int *lenPtr);
+JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
 JIM_EXPORT int Jim_Length(Jim_Obj *objPtr);
 
 /* string object */
@@ -721,6 +705,8 @@ JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp,
         Jim_Obj *objPtr, const char *str);
 JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr,
         Jim_Obj *secondObjPtr, int nocase);
+JIM_EXPORT int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr,
+        Jim_Obj *secondObjPtr, int nocase);
 JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr);
 
 /* reference object */
@@ -760,6 +746,8 @@ JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp,
 JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp,
         Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr,
         Jim_CallFrame *targetCallFrame);
+JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp,
+        Jim_Obj *nameObjPtr);
 JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp,
         Jim_Obj *nameObjPtr, int flags);
 JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp,
@@ -795,11 +783,14 @@ JIM_EXPORT void Jim_ListAppendList (Jim_Interp *interp,
 JIM_EXPORT int Jim_ListLength (Jim_Interp *interp, Jim_Obj *objPtr);
 JIM_EXPORT int Jim_ListIndex (Jim_Interp *interp, Jim_Obj *listPrt,
         int listindex, Jim_Obj **objPtrPtr, int seterr);
+JIM_EXPORT Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx);
 JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp,
         Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc,
         Jim_Obj *newObjPtr);
 JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc,
         Jim_Obj *const *objv);
+JIM_EXPORT Jim_Obj *Jim_ListJoin(Jim_Interp *interp,
+        Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen);
 
 /* dict object */
 JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp,
@@ -817,7 +808,9 @@ JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp,
 JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr,
         Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr);
 JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj);
+JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr);
 JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr);
+JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr);
 
 /* return code object */
 JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr,
@@ -845,12 +838,6 @@ JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr,
         double doubleValue);
 JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue);
 
-/* shared strings */
-JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp,
-        const char *str);
-JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp,
-        const char *str);
-
 /* commands utilities */
 JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
         Jim_Obj *const *argv, const char *msg);
@@ -886,10 +873,22 @@ JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp);
 
 /* interactive mode */
 JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp);
+JIM_EXPORT void Jim_HistoryLoad(const char *filename);
+JIM_EXPORT void Jim_HistorySave(const char *filename);
+JIM_EXPORT char *Jim_HistoryGetline(const char *prompt);
+JIM_EXPORT void Jim_HistoryAdd(const char *line);
+JIM_EXPORT void Jim_HistoryShow(void);
 
 /* Misc */
 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
+JIM_EXPORT int Jim_IsBigEndian(void);
+
+/**
+ * Returns 1 if a signal has been received while
+ * in a catch -signal {} clause.
+ */
+#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
 
 /* jim-load.c */
 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
@@ -898,7 +897,6 @@ JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
 /* jim-aio.c */
 JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command);
 
-
 /* type inspection - avoid where possible */
 JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
 JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
diff --git a/jim/jim_tcl.txt b/jim/jim_tcl.txt
new file mode 100755 (executable)
index 0000000..255d12b
--- /dev/null
@@ -0,0 +1,5062 @@
+Jim Tcl(n)
+==========
+
+NAME
+----
+Jim Tcl v0.75 - reference manual for the Jim Tcl scripting language
+
+SYNOPSIS
+--------
+
+  cc <source> -ljim
+
+or
+
+  jimsh [<scriptfile>]
+  jimsh -e '<immediate-script>'
+  jimsh --version
+
+
+.Quick Index
+* <<CommandIndex,Command Reference>>
+* <<OperatorPrecedence,Operator Precedence>>
+* <<BuiltinVariables, Builtin Variables>>
+* <<BackslashSequences, Backslash Sequences>>
+
+INTRODUCTION
+------------
+Jim Tcl is a small footprint reimplementation of the Tcl scripting language.
+The core language engine is compatible with Tcl 8.5+, while implementing
+a significant subset of the Tcl 8.6 command set, plus additional features
+available only in Jim Tcl.
+
+Some notable differences with Tcl 8.5/8.6 are:
+
+1. Object-based I/O (aio), but with a Tcl-compatibility layer
+2. I/O: Support for sockets and pipes including udp, unix domain sockets and IPv6
+3. Integers are 64bit
+4. Support for references (`ref`/`getref`/`setref`) and garbage collection
+5. Builtin dictionary type (`dict`) with some limitations compared to Tcl 8.6
+6. `env` command to access environment variables
+7. Operating system features: `os.fork`, `os.wait`, `os.uptime`, `signal`, `alarm`, `sleep`
+8. Much better error reporting. `info stacktrace` as a replacement for '$errorInfo', '$errorCode'
+9. Support for "static" variables in procedures
+10. Threads and coroutines are not supported
+11. Command and variable traces are not supported
+12. Built-in command line editing
+13. Expression shorthand syntax: +$(...)+
+14. Modular build allows many features to be omitted or built as dynamic, loadable modules
+15. Highly suitable for use in an embedded environment
+16. Support for UDP, IPv6, Unix-Domain sockets in addition to TCP sockets
+
+RECENT CHANGES
+--------------
+Changes between 0.74 and 0.75
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1. `binary`, `pack` and `unpack` now support floating point
+2. `file copy` '-force' handles source and target as the same file
+3. `format` now supports +%b+ for binary conversion
+4. `lsort` now supports '-unique' and '-real'
+5. Add support for half-close with `aio close` ?r|w?
+6. Add `socket pair` for a bidirectional pipe
+7. Add --random-hash to randomise hash tables for greater security
+8. `dict` now supports 'for', 'values', 'incr', 'append', 'lappend', 'update', 'info' and 'replace'
+9. `file stat` no longer requires the variable name
+
+Changes between 0.73 and 0.74
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1. Numbers with leading zeros are treated as decimal, not octal
+2. Add `aio isatty`
+3. Add LFS (64 bit) support for `aio seek`, `aio tell`, `aio copyto`, `file copy`
+4. `string compare` and `string equal` now support '-length'
+5. `glob` now supports '-directory'
+
+Changes between 0.72 and 0.73
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1. Built-in regexp now support non-capturing parentheses: (?:...)
+2. Add `string replace`
+3. Add `string totitle`
+4. Add `info statics`
+5. Add +build-jim-ext+ for easy separate building of loadable modules (extensions)
+6. `local` now works with any command, not just procs
+7. Add `info alias` to access the target of an alias
+8. UTF-8 encoding past the basic multilingual plane (BMP) is supported
+9. Add `tcl::prefix`
+10. Add `history`
+11. Most extensions are now enabled by default
+12. Add support for namespaces and the `namespace` command
+13. Add `apply`
+
+Changes between 0.71 and 0.72
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1. procs now allow 'args' and optional parameters in any position
+2. Add Tcl-compatible expr functions, `rand()`, `srand()` and `pow()`
+3. Add support for the '-force' option to `file delete`
+4. Better diagnostics when `source` fails to load a script with a missing quote or bracket
+5. New +tcl_platform(pathSeparator)+
+6. Add support settings the modification time with `file mtime`
+7. `exec` is now fully supported on win32 (mingw32)
+8. `file join`, `pwd`, `glob` etc. now work for mingw32
+9. Line editing is now supported for the win32 console (mingw32)
+10. Add `aio listen` command
+
+Changes between 0.70 and 0.71
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1. Allow 'args' to be renamed in procs
+2. Add +$(...)+ shorthand syntax for expressions
+3. Add automatic reference variables in procs with +&var+ syntax
+4. Support +jimsh --version+
+5. Additional variables in +tcl_platform()+
+6. `local` procs now push existing commands and `upcall` can call them
+7. Add `loop` command (TclX compatible)
+8. Add `aio buffering` command
+9. `info complete` can now return the missing character
+10. `binary format` and `binary scan` are now (optionally) supported
+11. Add `string byterange`
+12. Built-in regexp now support non-greedy repetition (*?, +?, ??)
+
+TCL INTRODUCTION
+-----------------
+Tcl stands for 'tool command language' and is pronounced 'tickle.'
+It is actually two things: a language and a library.
+
+First, Tcl is a simple textual language, intended primarily for
+issuing commands to interactive programs such as text editors,
+debuggers, illustrators, and shells.  It has a simple syntax and is also
+programmable, so Tcl users can write command procedures to provide more
+powerful commands than those in the built-in set.
+
+Second, Tcl is a library package that can be embedded in application
+programs.  The Tcl library consists of a parser for the Tcl language,
+routines to implement the Tcl built-in commands, and procedures that
+allow each application to extend Tcl with additional commands specific
+to that application.  The application program generates Tcl commands and
+passes them to the Tcl parser for execution.  Commands may be generated
+by reading characters from an input source, or by associating command
+strings with elements of the application's user interface, such as menu
+entries, buttons, or keystrokes.
+
+When the Tcl library receives commands it parses them into component
+fields and executes built-in commands directly.  For commands implemented
+by the application, Tcl calls back to the application to execute the
+commands.  In many cases commands will invoke recursive invocations of the
+Tcl interpreter by passing in additional strings to execute (procedures,
+looping commands, and conditional commands all work in this way).
+
+An application program gains three advantages by using Tcl for its command
+language.  First, Tcl provides a standard syntax:  once users know Tcl,
+they will be able to issue commands easily to any Tcl-based application.
+Second, Tcl provides programmability.  All a Tcl application needs
+to do is to implement a few application-specific low-level commands.
+Tcl provides many utility commands plus a general programming interface
+for building up complex command procedures.  By using Tcl, applications
+need not re-implement these features.
+
+Third, Tcl can be used as a common language for communicating between
+applications.  Inter-application communication is not built into the
+Tcl core described here, but various add-on libraries, such as the Tk
+toolkit, allow applications to issue commands to each other.  This makes
+it possible for applications to work together in much more powerful ways
+than was previously possible.
+
+Fourth, Jim Tcl includes a command processor, +jimsh+, which can be
+used to run standalone Tcl scripts, or to run Tcl commands interactively.
+
+This manual page focuses primarily on the Tcl language.  It describes
+the language syntax and the built-in commands that will be available
+in any application based on Tcl.  The individual library procedures are
+described in more detail in separate manual pages, one per procedure.
+
+JIMSH COMMAND INTERPRETER
+-------------------------
+A simple, but powerful command processor, +jimsh+, is part of Jim Tcl.
+It may be invoked in interactive mode as:
+
+  jimsh
+
+or to process the Tcl script in a file with:
+
+  jimsh filename
+
+It may also be invoked to execute an immediate script with:
+
+  jimsh -e "script"
+
+Interactive Mode
+~~~~~~~~~~~~~~~~
+Interactive mode reads Tcl commands from standard input, evaluates
+those commands and prints the results.
+
+  $ jimsh
+  Welcome to Jim version 0.73, Copyright (c) 2005-8 Salvatore Sanfilippo
+  . info version
+  0.73
+  . lsort [info commands p*]
+  package parray pid popen proc puts pwd
+  . foreach i {a b c} {
+  {> puts $i
+  {> }
+  a
+  b
+  c
+  . bad
+  invalid command name "bad"
+  [error] . exit
+  $
+
+If +jimsh+ is configured with line editing (it is by default) and a VT-100-compatible
+terminal is detected, Emacs-style line editing commands are available, including:
+arrow keys, +\^W+ to erase a word, +\^U+ to erase the line, +^R+ for reverse incremental search
+in history. Additionally, the +h+ command may be used to display the command history.
+
+Command line history is automatically saved and loaded from +~/.jim_history+
+
+In interactive mode, +jimsh+ automatically runs the script +~/.jimrc+ at startup
+if it exists.
+
+INTERPRETERS
+------------
+The central data structure in Tcl is an interpreter (C type 'Jim_Interp').
+An interpreter consists of a set of command bindings, a set of variable
+values, and a few other miscellaneous pieces of state.  Each Tcl command
+is interpreted in the context of a particular interpreter.
+
+Some Tcl-based applications will maintain multiple interpreters
+simultaneously, each associated with a different widget or portion of
+the application.  Interpreters are relatively lightweight structures.
+They can be created and deleted quickly, so application programmers should
+feel free to use multiple interpreters if that simplifies the application.
+
+DATA TYPES
+----------
+Tcl supports only one type of data:  strings.  All commands, all arguments
+to commands, all command results, and all variable values are strings.
+
+Where commands require numeric arguments or return numeric results,
+the arguments and results are passed as strings.  Many commands expect
+their string arguments to have certain formats, but this interpretation
+is up to the individual commands.  For example, arguments often contain
+Tcl command strings, which may get executed as part of the commands.
+The easiest way to understand the Tcl interpreter is to remember that
+everything is just an operation on a string.  In many cases Tcl constructs
+will look similar to more structured constructs from other languages.
+However, the Tcl constructs are not structured at all; they are just
+strings of characters, and this gives them a different behaviour than
+the structures they may look like.
+
+Although the exact interpretation of a Tcl string depends on who is doing
+the interpretation, there are three common forms that strings take:
+commands, expressions, and lists.  The major sections below discuss
+these three forms in more detail.
+
+BASIC COMMAND SYNTAX
+--------------------
+The Tcl language has syntactic similarities to both the Unix shells
+and Lisp.  However, the interpretation of commands is different
+in Tcl than in either of those other two systems.
+A Tcl command string consists of one or more commands separated
+by newline characters or semi-colons.
+Each command consists of a collection of fields separated by
+white space (spaces or tabs).
+The first field must be the name of a command, and the
+additional fields, if any, are arguments that will be passed to
+that command.  For example, the command:
+
+    set a 22
+
+has three fields:  the first, `set`, is the name of a Tcl command, and
+the last two, 'a' and '22', will be passed as arguments to
+the `set` command.  The command name may refer either to a built-in
+Tcl command, an application-specific command bound in with the library
+procedure 'Jim_CreateCommand', or a command procedure defined with the
+`proc` built-in command.
+
+Arguments are passed literally as text strings.  Individual commands may
+interpret those strings in any fashion they wish.  The `set` command,
+for example, will treat its first argument as the name of a variable
+and its second argument as a string value to assign to that variable.
+For other commands arguments may be interpreted as integers, lists,
+file names, or Tcl commands.
+
+Command names should normally be typed completely (e.g. no abbreviations).
+However, if the Tcl interpreter cannot locate a command it invokes a
+special command named `unknown` which attempts to find or create the
+command.
+
+For example, at many sites `unknown` will search through library
+directories for the desired command and create it as a Tcl procedure if
+it is found.  The `unknown` command often provides automatic completion
+of abbreviated commands, but usually only for commands that were typed
+interactively.
+
+It's probably a bad idea to use abbreviations in command scripts and
+other forms that will be re-used over time:  changes to the command set
+may cause abbreviations to become ambiguous, resulting in scripts that
+no longer work.
+
+COMMENTS
+--------
+If the first non-blank character in a command is +\#+, then everything
+from the +#+ up through the next newline character is treated as
+a comment and ignored.  When comments are embedded inside nested
+commands (e.g. fields enclosed in braces) they must have properly-matched
+braces (this is necessary because when Tcl parses the top-level command
+it doesn't yet know that the nested field will be used as a command so
+it cannot process the nested comment character as a comment).
+
+GROUPING ARGUMENTS WITH DOUBLE-QUOTES
+-------------------------------------
+Normally each argument field ends at the next white space, but
+double-quotes may be used to create arguments with embedded space.
+
+If an argument field begins with a double-quote, then the argument isn't
+terminated by white space (including newlines) or a semi-colon (see below
+for information on semi-colons); instead it ends at the next double-quote
+character.  The double-quotes are not included in the resulting argument.
+For example, the command
+
+    set a "This is a single argument"
+
+will pass two arguments to `set`:  'a' and 'This is a single argument'.
+
+Within double-quotes, command substitutions, variable substitutions,
+and backslash substitutions still occur, as described below.  If the
+first character of a command field is not a quote, then quotes receive
+no special interpretation in the parsing of that field.
+
+GROUPING ARGUMENTS WITH BRACES
+------------------------------
+Curly braces may also be used for grouping arguments.  They are similar
+to quotes except for two differences.  First, they nest; this makes them
+easier to use for complicated arguments like nested Tcl command strings.
+Second, the substitutions described below for commands, variables, and
+backslashes do *not* occur in arguments enclosed in braces, so braces
+can be used to prevent substitutions where they are undesirable.
+
+If an argument field begins with a left brace, then the argument ends
+at the matching right brace.  Tcl will strip off the outermost layer
+of braces and pass the information between the braces to the command
+without any further modification.  For example, in the command
+
+    set a {xyz a {b c d}}
+
+the `set` command will receive two arguments: 'a'
+and 'xyz a {b c d}'.
+
+When braces or quotes are in effect, the matching brace or quote need
+not be on the same line as the starting quote or brace; in this case
+the newline will be included in the argument field along with any other
+characters up to the matching brace or quote.  For example, the `eval`
+command takes one argument, which is a command string; `eval` invokes
+the Tcl interpreter to execute the command string.  The command
+
+    eval {
+      set a 22
+      set b 33
+    }
+
+will assign the value '22' to 'a' and '33' to 'b'.
+
+If the first character of a command field is not a left
+brace, then neither left nor right
+braces in the field will be treated specially (except as part of
+variable substitution; see below).
+
+COMMAND SUBSTITUTION WITH BRACKETS
+----------------------------------
+If an open bracket occurs in a field of a command, then command
+substitution occurs (except for fields enclosed in braces).  All of the
+text up to the matching close bracket is treated as a Tcl command and
+executed immediately.  Then the result of that command is substituted
+for the bracketed text.  For example, consider the command
+
+    set a [set b]
+
+When the `set` command has only a single argument, it is the name of a
+variable and `set` returns the contents of that variable.  In this case,
+if variable 'b' has the value 'foo', then the command above is equivalent
+to the command
+
+    set a foo
+
+Brackets can be used in more complex ways.  For example, if the variable
+'b' has the value 'foo' and the variable 'c' has the value 'gorp',
+then the command
+
+    set a xyz[set b].[set c]
+
+is equivalent to the command
+
+    set a xyzfoo.gorp
+
+
+A bracketed command may contain multiple commands separated by newlines
+or semi-colons in the usual fashion.  In this case the value of the last
+command is used for substitution.  For example, the command
+
+    set a x[set b 22
+    expr $b+2]x
+
+is equivalent to the command
+
+    set a x24x
+
+
+If a field is enclosed in braces then the brackets and the characters
+between them are not interpreted specially; they are passed through to
+the argument verbatim.
+
+VARIABLE SUBSTITUTION WITH $
+----------------------------
+The dollar sign (+$+) may be used as a special shorthand form for
+substituting variable values.  If +$+ appears in an argument that isn't
+enclosed in braces then variable substitution will occur.  The characters
+after the +$+, up to the first character that isn't a number, letter,
+or underscore, are taken as a variable name and the string value of that
+variable is substituted for the name.
+
+For example, if variable 'foo' has the value 'test', then the command
+
+    set a $foo.c
+
+is equivalent to the command
+
+    set a test.c
+
+There are two special forms for variable substitution.  If the next
+character after the name of the variable is an open parenthesis, then
+the variable is assumed to be an array name, and all of the characters
+between the open parenthesis and the next close parenthesis are taken as
+an index into the array.  Command substitutions and variable substitutions
+are performed on the information between the parentheses before it is
+used as an index.
+
+For example, if the variable 'x' is an array with one element named
+'first' and value '87' and another element named '14' and value 'more',
+then the command
+
+    set a xyz$x(first)zyx
+
+is equivalent to the command
+
+    set a xyz87zyx
+
+If the variable 'index' has the value '14', then the command
+
+    set a xyz$x($index)zyx
+
+is equivalent to the command
+
+    set a xyzmorezyx
+
+For more information on arrays, see VARIABLES AND ARRAYS below.
+
+The second special form for variables occurs when the dollar sign is
+followed by an open curly brace.  In this case the variable name consists
+of all the characters up to the next curly brace.
+
+Array references are not possible in this form:  the name between braces
+is assumed to refer to a scalar variable.  For example, if variable
+'foo' has the value 'test', then the command
+
+    set a abc${foo}bar
+
+is equivalent to the command
+
+    set a abctestbar
+
+
+Variable substitution does not occur in arguments that are enclosed in
+braces:  the dollar sign and variable name are passed through to the
+argument verbatim.
+
+The dollar sign abbreviation is simply a shorthand form.  +$a+ is
+completely equivalent to +[set a]+; it is provided as a convenience
+to reduce typing.
+
+SEPARATING COMMANDS WITH SEMI-COLONS
+------------------------------------
+Normally, each command occupies one line (the command is terminated by a
+newline character).  However, semi-colon (+;+) is treated as a command
+separator character; multiple commands may be placed on one line by
+separating them with a semi-colon.  Semi-colons are not treated as
+command separators if they appear within curly braces or double-quotes.
+
+BACKSLASH SUBSTITUTION
+----------------------
+Backslashes may be used to insert non-printing characters into command
+fields and also to insert special characters like braces and brackets
+into fields without them being interpreted specially as described above.
+
+The backslash sequences understood by the Tcl interpreter are
+listed below.  In each case, the backslash
+sequence is replaced by the given character:
+[[BackslashSequences]]
++{backslash}b+::
+    Backspace (0x8)
+
++{backslash}f+::
+    Form feed (0xc)
+
++{backslash}n+::
+    Newline (0xa)
+
++{backslash}r+::
+    Carriage-return (0xd).
+
++{backslash}t+::
+    Tab (0x9).
+
++{backslash}v+::
+    Vertical tab (0xb).
+
++{backslash}{+::
+    Left brace ({).
+
++{backslash}}+::
+    Right brace (}).
+
++{backslash}[+::
+    Open bracket ([).
+
++{backslash}]+::
+    Close bracket (]).
+
++{backslash}$+::
+    Dollar sign ($).
+
++{backslash}<space>+::
+    Space ( ): doesn't terminate argument.
+
++{backslash};+::
+    Semi-colon: doesn't terminate command.
+
++{backslash}"+::
+    Double-quote.
+
++{backslash}<newline>+::
+    Nothing:  this joins two lines together
+    into a single line.  This backslash feature is unique in that
+    it will be applied even when the sequence occurs within braces.
+
++{backslash}{backslash}+::
+    Backslash ('{backslash}').
+
++{backslash}ddd+::
+    The digits +'ddd'+ (one, two, or three of them) give the octal value of
+    the character.  Note that Jim supports null characters in strings.
+
++{backslash}unnnn+::
++{backslash}u\{nnn\}+::
++{backslash}Unnnnnnnn+::
+    The UTF-8 encoding of the unicode codepoint represented by the hex digits, +'nnnn'+, is inserted.
+    The 'u' form allows for one to four hex digits.
+    The 'U' form allows for one to eight hex digits.
+    The 'u\{nnn\}' form allows for one to eight hex digits, but makes it easier to insert
+    characters UTF-8 characters which are followed by a hex digit.
+
+For example, in the command
+
+    set a \{x\[\ yz\141
+
+the second argument to `set` will be +{x[ yza+.
+
+If a backslash is followed by something other than one of the options
+described above, then the backslash is transmitted to the argument
+field without any special processing, and the Tcl scanner continues
+normal processing with the next character.  For example, in the
+command
+
+    set \*a \\\{foo
+
+The first argument to `set` will be +{backslash}*a+ and the second
+argument will be +{backslash}{foo+.
+
+If an argument is enclosed in braces, then backslash sequences inside
+the argument are parsed but no substitution occurs (except for
+backslash-newline):  the backslash
+sequence is passed through to the argument as is, without making
+any special interpretation of the characters in the backslash sequence.
+In particular, backslashed braces are not counted in locating the
+matching right brace that terminates the argument.
+For example, in the
+command
+
+    set a {\{abc}
+
+the second argument to `set` will be +{backslash}{abc+.
+
+This backslash mechanism is not sufficient to generate absolutely
+any argument structure; it only covers the
+most common cases.  To produce particularly complicated arguments
+it is probably easiest to use the `format` command along with
+command substitution.
+
+STRING AND LIST INDEX SPECIFICATIONS
+------------------------------------
+
+Many string and list commands take one or more 'index' parameters which
+specify a position in the string relative to the start or end of the string/list.
+
+The index may be one of the following forms:
+
++integer+::
+    A simple integer, where '0' refers to the first element of the string
+    or list.
+
++integer+integer+ or::
++integer-integer+::
+    The sum or difference of the two integers. e.g. +2+3+ refers to the 5th element.
+    This is useful when used with (e.g.) +$i+1+ rather than the more verbose
+    +[expr {$i+1\}]+
+
++end+::
+    The last element of the string or list.
+
++end-integer+::
+    The 'nth-from-last' element of the string or list.
+
+COMMAND SUMMARY
+---------------
+1. A command is just a string.
+2. Within a string commands are separated by newlines or semi-colons
+   (unless the newline or semi-colon is within braces or brackets
+   or is backslashed).
+3. A command consists of fields.  The first field is the name of the command.
+   The other fields are strings that are passed to that command as arguments.
+4. Fields are normally separated by white space.
+5. Double-quotes allow white space and semi-colons to appear within
+   a single argument.
+   Command substitution, variable substitution, and backslash substitution
+   still occur inside quotes.
+6. Braces defer interpretation of special characters.
+   If a field begins with a left brace, then it consists of everything
+   between the left brace and the matching right brace. The
+   braces themselves are not included in the argument.
+   No further processing is done on the information between the braces
+   except that backslash-newline sequences are eliminated.
+7. If a field doesn't begin with a brace then backslash,
+   variable, and command substitution are done on the field.  Only a
+   single level of processing is done:  the results of one substitution
+   are not scanned again for further substitutions or any other
+   special treatment.  Substitution can
+   occur on any field of a command, including the command name
+   as well as the arguments.
+8. If the first non-blank character of a command is a +\#+, everything
+   from the +#+ up through the next newline is treated as a comment
+   and ignored.
+
+EXPRESSIONS
+-----------
+The second major interpretation applied to strings in Tcl is
+as expressions.  Several commands, such as `expr`, `for`,
+and `if`, treat one or more of their arguments as expressions
+and call the Tcl expression processors ('Jim_ExprLong',
+'Jim_ExprBoolean', etc.) to evaluate them.
+
+The operators permitted in Tcl expressions are a subset of
+the operators permitted in C expressions, and they have the
+same meaning and precedence as the corresponding C operators.
+Expressions almost always yield numeric results
+(integer or floating-point values).
+For example, the expression
+
+    8.2 + 6
+
+evaluates to 14.2.
+
+Tcl expressions differ from C expressions in the way that
+operands are specified, and in that Tcl expressions support
+non-numeric operands and string comparisons.
+
+A Tcl expression consists of a combination of operands, operators,
+and parentheses.
+
+White space may be used between the operands and operators and
+parentheses; it is ignored by the expression processor.
+Where possible, operands are interpreted as integer values.
+
+Integer values may be specified in decimal (the normal case) or in
+hexadecimal (if the first two characters of the operand are '0x').
+Note that Jim Tcl does *not* treat numbers with leading zeros as octal.
+
+If an operand does not have one of the integer formats given
+above, then it is treated as a floating-point number if that is
+possible.  Floating-point numbers may be specified in any of the
+ways accepted by an ANSI-compliant C compiler (except that the
+'f', 'F', 'l', and 'L' suffixes will not be permitted in
+most installations).  For example, all of the
+following are valid floating-point numbers:  2.1, 3., 6e4, 7.91e+16.
+
+If no numeric interpretation is possible, then an operand is left
+as a string (and only a limited set of operators may be applied to
+it).
+
+1. Operands may be specified in any of the following ways:
+
+2. As a numeric value, either integer or floating-point.
+
+3. As a Tcl variable, using standard '$' notation.
+The variable's value will be used as the operand.
+
+4. As a string enclosed in double-quotes.
+The expression parser will perform backslash, variable, and
+command substitutions on the information between the quotes,
+and use the resulting value as the operand
+
+5. As a string enclosed in braces.
+The characters between the open brace and matching close brace
+will be used as the operand without any substitutions.
+
+6. As a Tcl command enclosed in brackets.
+The command will be executed and its result will be used as
+the operand.
+
+Where substitutions occur above (e.g. inside quoted strings), they
+are performed by the expression processor.
+However, an additional layer of substitution may already have
+been performed by the command parser before the expression
+processor was called.
+
+As discussed below, it is usually best to enclose expressions
+in braces to prevent the command parser from performing substitutions
+on the contents.
+
+For some examples of simple expressions, suppose the variable 'a' has
+the value 3 and the variable 'b' has the value 6.  Then the expression
+on the left side of each of the lines below will evaluate to the value
+on the right side of the line:
+
+    $a + 3.1                6.1
+    2 + "$a.$b"             5.6
+    4*[llength "6 2"]       8
+    {word one} < "word $a"  0
+
+The valid operators are listed below, grouped in decreasing order
+of precedence:
+[[OperatorPrecedence]]
++int() double() round() abs(), rand(), srand()+::
+    Unary functions (except rand() which takes no arguments)
+    * +'int()'+ converts the numeric argument to an integer by truncating down.
+    * +'double()'+ converts the numeric argument to floating point.
+    * +'round()'+ converts the numeric argument to the closest integer value.
+    * +'abs()'+ takes the absolute value of the numeric argument.
+    * +'rand()'+ takes the absolute value of the numeric argument.
+    * +'rand()'+ returns a pseudo-random floating-point value in the range (0,1).
+    * +'srand()'+ takes an integer argument to (re)seed the random number generator. Returns the first random number from that seed.
+
++sin() cos() tan() asin() acos() atan() sinh() cosh() tanh() ceil() floor() exp() log() log10() sqrt()+::
+    Unary math functions.
+    If Jim is compiled with math support, these functions are available.
+
++- + ~ !+::
+    Unary minus, unary plus, bit-wise NOT, logical NOT.  None of these operands
+    may be applied to string operands, and bit-wise NOT may be
+    applied only to integers.
+
++** pow(x,y)+::
+    Power. e.g. 'x^y^'. If Jim is compiled with math support, supports doubles and
+    integers. Otherwise supports integers only. (Note that the math-function form
+    has the same highest precedence)
+
++* / %+::
+    Multiply, divide, remainder.  None of these operands may be
+    applied to string operands, and remainder may be applied only
+    to integers.
+
+++ -+::
+    Add and subtract.  Valid for any numeric operands.
+
++<<  >> <<< >>>+::
+    Left and right shift, left and right rotate.  Valid for integer operands only.
+
++<  >  \<=  >=+::
+    Boolean less, greater, less than or equal, and greater than or equal.
+    Each operator produces 1 if the condition is true, 0 otherwise.
+    These operators may be applied to strings as well as numeric operands,
+    in which case string comparison is used.
+
++==  !=+::
+    Boolean equal and not equal.  Each operator produces a zero/one result.
+    Valid for all operand types. *Note* that values will be converted to integers
+    if possible, then floating point types, and finally strings will be compared.
+    It is recommended that 'eq' and 'ne' should be used for string comparison.
+
++eq ne+::
+    String equal and not equal.  Uses the string value directly without
+    attempting to convert to a number first.
+
++in ni+::
+    String in list and not in list. For 'in', result is 1 if the left operand (as a string)
+    is contained in the right operand (as a list), or 0 otherwise. The result for
+    +{$a ni $list}+ is equivalent to +{!($a in $list)}+.
+
++&+::
+    Bit-wise AND.  Valid for integer operands only.
+
++|+::
+    Bit-wise OR.  Valid for integer operands only.
+
++^+::
+    Bit-wise exclusive OR.  Valid for integer operands only.
+
++&&+::
+    Logical AND.  Produces a 1 result if both operands are non-zero, 0 otherwise.
+    Valid for numeric operands only (integers or floating-point).
+
++||+::
+    Logical OR.  Produces a 0 result if both operands are zero, 1 otherwise.
+    Valid for numeric operands only (integers or floating-point).
+
++x ? y : z+::
+    If-then-else, as in C.  If +'x'+
+    evaluates to non-zero, then the result is the value of +'y'+.
+    Otherwise the result is the value of +'z'+.
+    The +'x'+ operand must have a numeric value, while +'y'+ and +'z'+ can
+    be of any type.
+
+See the C manual for more details on the results
+produced by each operator.
+All of the binary operators group left-to-right within the same
+precedence level.  For example, the expression
+
+    4*2 < 7
+
+evaluates to 0.
+
+The +&&+, +||+, and +?:+ operators have 'lazy evaluation', just as
+in C, which means that operands are not evaluated if they are not
+needed to determine the outcome.  For example, in
+
+    $v ? [a] : [b]
+
+only one of +[a]+ or +[b]+ will actually be evaluated,
+depending on the value of +$v+.
+
+All internal computations involving integers are done with the C
+type 'long long' if available, or 'long' otherwise, and all internal
+computations involving floating-point are done with the C type
+'double'.
+
+When converting a string to floating-point, exponent overflow is
+detected and results in a Tcl error.
+For conversion to integer from string, detection of overflow depends
+on the behaviour of some routines in the local C library, so it should
+be regarded as unreliable.
+In any case, overflow and underflow are generally not detected
+reliably for intermediate results.
+
+Conversion among internal representations for integer, floating-point,
+and string operands is done automatically as needed.
+For arithmetic computations, integers are used until some
+floating-point number is introduced, after which floating-point is used.
+For example,
+
+    5 / 4
+
+yields the result 1, while
+
+    5 / 4.0
+    5 / ( [string length "abcd"] + 0.0 )
+
+both yield the result 1.25.
+
+String values may be used as operands of the comparison operators,
+although the expression evaluator tries to do comparisons as integer
+or floating-point when it can.
+If one of the operands of a comparison is a string and the other
+has a numeric value, the numeric operand is converted back to
+a string using the C 'sprintf' format specifier
+'%d' for integers and '%g' for floating-point values.
+For example, the expressions
+
+    "0x03" > "2"
+    "0y" < "0x12"
+
+both evaluate to 1.  The first comparison is done using integer
+comparison, and the second is done using string comparison after
+the second operand is converted to the string '18'.
+
+In general it is safest to enclose an expression in braces when
+entering it in a command:  otherwise, if the expression contains
+any white space then the Tcl interpreter will split it
+among several arguments.  For example, the command
+
+    expr $a + $b
+
+results in three arguments being passed to `expr`:  +$a+,
+\+, and +$b+.  In addition, if the expression isn't in braces
+then the Tcl interpreter will perform variable and command substitution
+immediately (it will happen in the command parser rather than in
+the expression parser).  In many cases the expression is being
+passed to a command that will evaluate the expression later (or
+even many times if, for example, the expression is to be used to
+decide when to exit a loop).  Usually the desired goal is to re-do
+the variable or command substitutions each time the expression is
+evaluated, rather than once and for all at the beginning.  For example,
+the command
+
+    for {set i 1} $i<=10 {incr i} {...}        ** WRONG **
+
+is probably intended to iterate over all values of +i+ from 1 to 10.
+After each iteration of the body of the loop, `for` will pass
+its second argument to the expression evaluator to see whether or not
+to continue processing.  Unfortunately, in this case the value of +i+
+in the second argument will be substituted once and for all when the
+`for` command is parsed.  If +i+ was 0 before the `for`
+command was invoked then the second argument of `for` will be +0\<=10+
+which will always evaluate to 1, even though +i+ eventually
+becomes greater than 10.  In the above case the loop will never
+terminate.  Instead, the expression should be placed in braces:
+
+    for {set i 1} {$i<=10} {incr i} {...}      ** RIGHT **
+
+This causes the substitution of 'i'
+to be delayed; it will be re-done each time the expression is
+evaluated, which is the desired result.
+
+LISTS
+-----
+The third major way that strings are interpreted in Tcl is as lists.
+A list is just a string with a list-like structure
+consisting of fields separated by white space.  For example, the
+string
+
+    Al Sue Anne John
+
+is a list with four elements or fields.
+Lists have the same basic structure as command strings, except
+that a newline character in a list is treated as a field separator
+just like space or tab.  Conventions for braces and quotes
+and backslashes are the same for lists as for commands.  For example,
+the string
+
+    a b\ c {d e {f g h}}
+
+is a list with three elements:  +a+, +b c+, and +d e {f g h}+.
+
+Whenever an element is extracted from a list, the same rules about
+braces and quotes and backslashes are applied as for commands.  Thus in
+the example above when the third element is extracted from the list,
+the result is
+
+    d e {f g h}
+
+(when the field was extracted, all that happened was to strip off
+the outermost layer of braces).  Command substitution and
+variable substitution are never
+made on a list (at least, not by the list-processing commands; the
+list can always be passed to the Tcl interpreter for evaluation).
+
+The Tcl commands `concat`, `foreach`, `lappend`, `lindex`, `linsert`,
+`list`, `llength`, `lrange`, `lreplace`, `lsearch`, and `lsort` allow
+you to build lists, extract elements from them, search them, and perform
+other list-related functions.
+
+Advanced list commands include `lrepeat`, `lreverse`, `lmap`, `lassign`, `lset`.
+
+LIST EXPANSION
+--------------
+
+A new addition to Tcl 8.5 is the ability to expand a list into separate
+arguments. Support for this feature is also available in Jim.
+
+Consider the following attempt to exec a list:
+
+    set cmd {ls -l}
+    exec $cmd
+
+This will attempt to exec the a command named "ls -l", which will clearly not
+work. Typically eval and concat are required to solve this problem, however
+it can be solved much more easily with +\{*\}+.
+
+    exec {*}$cmd
+
+This will expand the following argument into individual elements and then evaluate
+the resulting command.
+
+Note that the official Tcl syntax is +\{*\}+, however +\{expand\}+ is retained
+for backward compatibility with experimental versions of this feature.
+
+REGULAR EXPRESSIONS
+-------------------
+Tcl provides two commands that support string matching using regular
+expressions, `regexp` and `regsub`, as well as `switch -regexp` and
+`lsearch -regexp`.
+
+Regular expressions may be implemented one of two ways. Either using the system's C library
+POSIX regular expression support, or using the built-in regular expression engine.
+The differences between these are described below.
+
+*NOTE* Tcl 7.x and 8.x use perl-style Advanced Regular Expressions (+ARE+).
+
+POSIX Regular Expressions
+~~~~~~~~~~~~~~~~~~~~~~~~~
+If the system supports POSIX regular expressions, and UTF-8 support is not enabled,
+this support will be used by default. The type of regular expressions supported are
+Extended Regular Expressions (+ERE+) rather than Basic Regular Expressions (+BRE+).
+See REG_EXTENDED in the documentation.
+
+Using the system-supported POSIX regular expressions will typically
+make for the smallest code size, but some features such as UTF-8
+and +{backslash}w+, +{backslash}d+, +{backslash}s+ are not supported.
+
+See regex(3) and regex(7) for full details.
+
+Jim built-in Regular Expressions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The Jim built-in regulare expression engine may be selected with +./configure --with-jim-regexp+
+or it will be selected automatically if UTF-8 support is enabled.
+
+This engine supports UTF-8 as well as some +ARE+ features. The differences with both Tcl 7.x/8.x
+and POSIX are highlighted below.
+
+1. UTF-8 strings and patterns are both supported
+2. Supported character classes: +[:alnum:]+, +[:digit:]+ and +[:space:]+
+3. Supported shorthand character classes: +{backslash}w+ = +[:alnum:]+, +{backslash}d+ = +[:digit:],+ +{backslash}s+ = +[:space:]+
+4. Character classes apply to ASCII characters only
+5. Supported constraint escapes: +{backslash}m+ = +{backslash}<+ = start of word, +{backslash}M+ = +{backslash}>+ = end of word
+6. Backslash escapes may be used within regular expressions, such as +{backslash}n+ = newline, +{backslash}uNNNN+ = unicode
+7. Support for the +?+ non-greedy quantifier. e.g. +*?+
+8. Support for non-capuring parentheses +(?:...)+
+
+COMMAND RESULTS
+---------------
+Each command produces two results:  a code and a string.  The
+code indicates whether the command completed successfully or not,
+and the string gives additional information.  The valid codes are
+defined in jim.h, and are:
+
++JIM_OK(0)+::
+    This is the normal return code, and indicates that the command completed
+    successfully.  The string gives the command's return value.
+
++JIM_ERR(1)+::
+    Indicates that an error occurred; the string gives a message describing
+    the error.
+
++JIM_RETURN(2)+::
+    Indicates that the `return` command has been invoked, and that the
+    current procedure (or top-level command or `source` command)
+    should return immediately.  The
+    string gives the return value for the procedure or command.
+
++JIM_BREAK(3)+::
+    Indicates that the `break` command has been invoked, so the
+    innermost loop should abort immediately.  The string should always
+    be empty.
+
++JIM_CONTINUE(4)+::
+    Indicates that the `continue` command has been invoked, so the
+    innermost loop should go on to the next iteration.  The string
+    should always be empty.
+
++JIM_SIGNAL(5)+::
+    Indicates that a signal was caught while executing a commands.
+    The string contains the name of the signal caught.
+    See the `signal` and `catch` commands.
+
++JIM_EXIT(6)+::
+    Indicates that the command called the `exit` command.
+    The string contains the exit code.
+
+Tcl programmers do not normally need to think about return codes,
+since +JIM_OK+ is almost always returned.  If anything else is returned
+by a command, then the Tcl interpreter immediately stops processing
+commands and returns to its caller.  If there are several nested
+invocations of the Tcl interpreter in progress, then each nested
+command will usually return the error to its caller, until eventually
+the error is reported to the top-level application code.  The
+application will then display the error message for the user.
+
+In a few cases, some commands will handle certain `error` conditions
+themselves and not return them upwards.  For example, the `for`
+command checks for the +JIM_BREAK+ code; if it occurs, then `for`
+stops executing the body of the loop and returns +JIM_OK+ to its
+caller.  The `for` command also handles +JIM_CONTINUE+ codes and the
+procedure interpreter handles +JIM_RETURN+ codes.  The `catch`
+command allows Tcl programs to catch errors and handle them without
+aborting command interpretation any further.
+
+The `info returncodes` command may be used to programmatically map between
+return codes and names.
+
+PROCEDURES
+----------
+Tcl allows you to extend the command interface by defining
+procedures.  A Tcl procedure can be invoked just like any other Tcl
+command (it has a name and it receives one or more arguments).
+The only difference is that its body isn't a piece of C code linked
+into the program; it is a string containing one or more other
+Tcl commands.
+
+The `proc` command is used to create a new Tcl command procedure:
+
++*proc* 'name arglist ?statics? body'+
+
+The new command is named +'name'+, and it replaces any existing command
+there may have been by that name. Whenever the new command is
+invoked, the contents of +'body'+ will be executed by the Tcl
+interpreter.
+
++'arglist'+ specifies the formal arguments to the procedure.
+It consists of a list, possibly empty, of the following
+argument specifiers:
+
++name+::
+    Required Argument - A simple argument name.
+
++name default+::
+    Optional Argument - A two-element list consisting of the
+    argument name, followed by the default value, which will
+    be used if the corresponding argument is not supplied.
+
++&name+::
+    Reference Argument - The caller is expected to pass the name of
+    an existing variable. An implicit `upvar 1 'origname' 'name'` is done
+    to make the variable available in the proc scope.
+
++*args*+::
+    Variable Argument - The special name +'args'+, which is
+    assigned all remaining arguments (including none) as a list. The
+    variable argument may only be specified once. Note that
+    the syntax +args newname+ may be used to retain the special
+    behaviour of +'args'+ with a different local name. In this case,
+    the variable is named +'newname'+ rather than +'args'+.
+
+When the command is invoked, a local variable will be created for each of
+the formal arguments to the procedure; its value will be the value
+of corresponding argument in the invoking command or the argument's
+default value.
+
+Arguments with default values need not be specified in a procedure
+invocation.  However, there must be enough actual arguments for all
+required arguments, and there must not be any extra actual arguments
+(unless the Variable Argument is specified).
+
+Actual arguments are assigned to formal arguments as in left-to-right
+order with the following precedence.
+
+1. Required Arguments (including Reference Arguments)
+2. Optional Arguments
+3. Variable Argument
+
+The following example illustrates precedence. Assume a procedure declaration:
+
+    proc p {{a A} args b {c C} d} {...}
+
+This procedure requires at least two arguments, but can accept an unlimited number.
+The following table shows how various numbers of arguments are assigned.
+Values marked as +-+ are assigned the default value.
+
+[width="40%",frame="topbot",options="header"]
+|==============
+|Number of arguments|a|args|b|c|d
+|2|-|-|1|-|2
+|3|1|-|2|-|3
+|4|1|-|2|3|4
+|5|1|2|3|4|5
+|6|1|2,3|4|5|6
+|==============
+
+When +'body'+ is being executed, variable names normally refer to local
+variables, which are created automatically when referenced and deleted
+when the procedure returns.  One local variable is automatically created
+for each of the procedure's arguments.  Global variables can be
+accessed by invoking the `global` command or via the +::+ prefix.
+
+New in Jim
+~~~~~~~~~~
+In addition to procedure arguments, Jim procedures may declare static variables.
+These variables scoped to the procedure and initialised at procedure definition.
+Either from the static variable definition, or from the enclosing scope.
+
+Consider the following example:
+
+    jim> set a 1
+    jim> proc a {} {a {b 2}} {
+        set c 1
+        puts "$a $b $c"
+        incr a
+        incr b
+        incr c
+    }
+    jim> a
+    1 2 1
+    jim> a
+    2 3 1
+
+The static variable +'a'+ has no initialiser, so it is initialised from
+the enclosing scope with the value 1. (Note that it is an error if there
+is no variable with the same name in the enclosing scope). However +'b'+
+has an initialiser, so it is initialised to 2.
+
+Unlike a local variable, the value of a static variable is retained across
+invocations of the procedure.
+
+See the `proc` command for information on how to define procedures
+and what happens when they are invoked. See also NAMESPACES.
+
+VARIABLES - SCALARS AND ARRAYS
+------------------------------
+Tcl allows the definition of variables and the use of their values
+either through '$'-style variable substitution, the `set`
+command, or a few other mechanisms.
+
+Variables need not be declared:  a new variable will automatically
+be created each time a new variable name is used.
+
+Tcl supports two types of variables:  scalars and arrays.
+A scalar variable has a single value, whereas an array variable
+can have any number of elements, each with a name (called
+its 'index') and a value.
+
+Array indexes may be arbitrary strings; they need not be numeric.
+Parentheses are used refer to array elements in Tcl commands.
+For example, the command
+
+    set x(first) 44
+
+will modify the element of 'x' whose index is 'first'
+so that its new value is '44'.
+
+Two-dimensional arrays can be simulated in Tcl by using indexes
+that contain multiple concatenated values.
+For example, the commands
+
+    set a(2,3) 1
+    set a(3,6) 2
+
+set the elements of 'a' whose indexes are '2,3' and '3,6'.
+
+In general, array elements may be used anywhere in Tcl that scalar
+variables may be used.
+
+If an array is defined with a particular name, then there may
+not be a scalar variable with the same name.
+
+Similarly, if there is a scalar variable with a particular
+name then it is not possible to make array references to the
+variable.
+
+To convert a scalar variable to an array or vice versa, remove
+the existing variable with the `unset` command.
+
+The `array` command provides several features for dealing
+with arrays, such as querying the names of all the elements of
+the array and converting between an array and a list.
+
+Variables may be either global or local.  If a variable
+name is used when a procedure isn't being executed, then it
+automatically refers to a global variable.  Variable names used
+within a procedure normally refer to local variables associated with that
+invocation of the procedure.  Local variables are deleted whenever
+a procedure exits.  Either `global` command may be used to request
+that a name refer to a global variable for the duration of the current
+procedure (this is somewhat analogous to 'extern' in C), or the variable
+may be explicitly scoped with the +::+ prefix. For example
+
+    set a 1
+    set b 2
+    proc p {} {
+        set c 3
+        global a
+
+        puts "$a $::b $c"
+    }
+    p
+
+will output:
+
+    1 2 3
+
+ARRAYS AS LISTS IN JIM
+----------------------
+Unlike Tcl, Jim can automatically convert between a list (with an even
+number of elements) and an array value. This is similar to the way Tcl
+can convert between a string and a list.
+
+For example:
+
+  set a {1 one 2 two}
+  puts $a(2)
+
+will output:
+
+  two
+
+Thus `array set` is equivalent to `set` when the variable does not
+exist or is empty.
+
+The reverse is also true where an array will be converted into
+a list.
+
+  set a(1) one; set a(2) two
+  puts $a
+
+will output:
+
+  1 one 2 two
+
+DICTIONARY VALUES
+-----------------
+Tcl 8.5 introduced the dict command, and Jim Tcl has added a version
+of this command. Dictionaries provide efficient access to key-value
+pairs, just like arrays, but dictionaries are pure values. This
+means that you can pass them to a procedure just as a list or a
+string. Tcl dictionaries are therefore much more like Tcl lists,
+except that they represent a mapping from keys to values, rather
+than an ordered sequence.
+
+You can nest dictionaries, so that the value for a particular key
+consists of another dictionary. That way you can elegantly build
+complicated data structures, such as hierarchical databases. You
+can also combine dictionaries with other Tcl data structures. For
+instance, you can build a list of dictionaries that themselves
+contain lists.
+
+Dictionaries are values that contain an efficient, order-preserving
+mapping from arbitrary keys to arbitrary values. Each key in the
+dictionary maps to a single value. They have a textual format that
+is exactly that of any list with an even number of elements, with
+each mapping in the dictionary being represented as two items in
+the list. When a command takes a dictionary and produces a new
+dictionary based on it (either returning it or writing it back into
+the variable that the starting dictionary was read from) the new
+dictionary will have the same order of keys, modulo any deleted
+keys and with new keys added on to the end. When a string is
+interpreted as a dictionary and it would otherwise have duplicate
+keys, only the last value for a particular key is used; the others
+are ignored, meaning that, "apple banana" and "apple carrot apple
+banana" are equivalent dictionaries (with different string
+representations).
+
+Note that in Jim, arrays are implemented as dictionaries.
+Thus automatic conversion between lists and dictionaries applies
+as it does for arrays.
+
+  jim> dict set a 1 one
+  1 one
+  jim> dict set a 2 two
+  1 one 2 two
+  jim> puts $a
+  1 one 2 two
+  jim> puts $a(2)
+  two
+  jim> dict set a 3 T three
+  1 one 2 two 3 {T three}
+
+See the `dict` command for more details.
+
+NAMESPACES
+----------
+Tcl added namespaces as a mechanism avoiding name clashes, especially in applications
+including a number of 3rd party components. While there is less need for namespaces
+in Jim Tcl (which does not strive to support large applications), it is convenient to
+provide a subset of the support for namespaces to easy porting code from Tcl.
+
+Jim Tcl currently supports "light-weight" namespaces which should be adequate for most
+purposes. This feature is currently experimental. See README.namespaces for more information
+and the documentation of the `namespace` command.
+
+GARBAGE COLLECTION, REFERENCES, LAMBDA
+--------------------------------------
+Unlike Tcl, Jim has some sophisticated support for functional programming.
+These are described briefly below.
+
+More information may be found at http://wiki.tcl.tk/13847
+
+References
+~~~~~~~~~~
+A reference can be thought of as holding a value with one level of indirection,
+where the value may be garbage collected when unreferenced.
+Consider the following example:
+
+    jim> set r [ref "One String" test]
+    <reference.<test___>.00000000000000000000>
+    jim> getref $r
+    One String
+
+The operation `ref` creates a references to the value specified by the
+first argument. (The second argument is a "type" used for documentation purposes).
+
+The operation `getref` is the dereferencing operation which retrieves the value
+stored in the reference.
+
+    jim> setref $r "New String"
+    New String
+    jim> getref $r
+    New String
+
+The operation `setref` replaces the value stored by the reference. If the old value
+is no longer accessible by any reference, it will eventually be automatically be garbage
+collected.
+
+Garbage Collection
+~~~~~~~~~~~~~~~~~~
+Normally, all values in Tcl are passed by value. As such values are copied and released
+automatically as necessary.
+
+With the introduction of references, it is possible to create values whose lifetime
+transcend their scope. To support this, case, the Jim system will periodically identify
+and discard objects which are no longer accessible by any reference.
+
+The `collect` command may be used to force garbage collection.  Consider a reference created
+with a finalizer:
+
+    jim> proc f {ref value} { puts "Finaliser called for $ref,$value" }
+    jim> set r [ref "One String" test f]
+    <reference.<test___>.00000000000
+    jim> collect
+    0
+    jim> set r ""
+    jim> collect
+    Finaliser called for <reference.<test___>.00000000000,One String
+    1
+
+Note that once the reference, 'r', was modified so that it no longer
+contained a reference to the value, the garbage collector discarded
+the value (after calling the finalizer).
+
+The finalizer for a reference may be examined or changed with the `finalize` command
+
+    jim> finalize $r
+    f
+    jim> finalize $r newf
+    newf
+
+Lambda
+~~~~~~
+Jim provides a garbage collected lambda function. This is a procedure
+which is able to create an anonymous procedure.  Consider:
+
+    jim> set f [lambda {a} {{x 0}} { incr x $a }]
+    jim> $f 1
+    1
+    jim> $f 2
+    3
+    jim> set f ""
+
+This create an anonymous procedure (with the name stored in 'f'), with a static variable
+which is incremented by the supplied value and the result returned.
+
+Once the procedure name is no longer accessible, it will automatically be deleted
+when the garbage collector runs.
+
+The procedure may also be delete immediately by renaming it "". e.g.
+
+    jim> rename $f ""
+
+UTF-8 AND UNICODE
+-----------------
+If Jim is built with UTF-8 support enabled (configure --enable-utf),
+then most string-related commands become UTF-8 aware.  These include,
+but are not limited to, `string match`, `split`, `glob`, `scan` and
+`format`.
+
+UTF-8 encoding has many advantages, but one of the complications is that
+characters can take a variable number of bytes. Thus the addition of
+`string bytelength` which returns the number of bytes in a string,
+while `string length` returns the number of characters.
+
+If UTF-8 support is not enabled, all commands treat bytes as characters
+and `string bytelength` returns the same value as `string length`.
+
+Note that even if UTF-8 support is not enabled, the +{backslash}uNNNN+ and related syntax
+is still available to embed UTF-8 sequences.
+
+Jim Tcl supports all currently defined unicode codepoints. That is 21 bits, up to +'U+1FFFFF'.
+
+String Matching
+~~~~~~~~~~~~~~~
+Commands such as `string match`, `lsearch -glob`, `array names` and others use string
+pattern matching rules. These commands support UTF-8. For example:
+
+  string match a\[\ua0-\ubf\]b "a\u00a3b"
+
+format and scan
+~~~~~~~~~~~~~~~
++format %c+ allows a unicode codepoint to be be encoded. For example, the following will return
+a string with two bytes and one character. The same as +{backslash}ub5+
+
+  format %c 0xb5
+
+`format` respects widths as character widths, not byte widths. For example, the following will
+return a string with three characters, not three bytes.
+
+  format %.3s \ub5\ub6\ub7\ub8
+
+Similarly, +scan ... %c+ allows a UTF-8 to be decoded to a unicode codepoint. The following will set
++'a'+ to 181 (0xb5) and +'b'+ to 65 (0x41).
+
+  scan \u00b5A %c%c a b
+
+`scan %s` will also accept a character class, including unicode ranges.
+
+String Classes
+~~~~~~~~~~~~~~
+`string is` has *not* been extended to classify UTF-8 characters. Therefore, the following
+will return 0, even though the string may be considered to be alphabetic.
+
+  string is alpha \ub5Test
+
+This does not affect the string classes 'ascii', 'control', 'digit', 'double', 'integer' or 'xdigit'.
+
+Case Mapping and Conversion
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Jim provides a simplified unicode case mapping. This means that case conversion
+and comparison will not increase or decrease the number of characters in a string.
+(Although it may change the number of bytes).
+
+`string toupper` will convert any lowercase letters to their uppercase equivalent.
+Any character which is not a letter or has no uppercase equivalent is left unchanged.
+Similarly for `string tolower` and `string totitle`.
+
+Commands which perform case insensitive matches, such as `string compare -nocase`
+and `lsearch -nocase` fold both strings to uppercase before comparison.
+
+Invalid UTF-8 Sequences
+~~~~~~~~~~~~~~~~~~~~~~~
+Some UTF-8 character sequences are invalid, such as those beginning with '0xff',
+those which represent character sequences longer than 3 bytes (greater than U+FFFF),
+and those which end prematurely, such as a lone '0xc2'.
+
+In these situations, the offending bytes are treated as single characters. For example,
+the following returns 2.
+
+  string bytelength \xff\xff
+
+Regular Expressions
+~~~~~~~~~~~~~~~~~~~
+If UTF-8 support is enabled, the built-in regular expression engine will be
+selected which supports UTF-8 strings and patterns.
+
+See REGULAR EXPRESSIONS
+
+BUILT-IN COMMANDS
+-----------------
+The Tcl library provides the following built-in commands, which will
+be available in any application using Tcl.  In addition to these
+built-in commands, there may be additional commands defined by each
+application, plus commands defined as Tcl procedures.
+
+In the command syntax descriptions below, words in +*boldface*+ are
+literals that you type verbatim to Tcl.
+
+Words in +'italics'+ are meta-symbols; they serve as names for any of
+a range of values that you can type.
+
+Optional arguments or groups of arguments are indicated by enclosing them
+in +?question-marks?+.
+
+Ellipses (+\...+) indicate that any number of additional
+arguments or groups of arguments may appear, in the same format
+as the preceding argument(s).
+
+[[CommandIndex]]
+Command Index
+~~~~~~~~~~~~~
+@INSERTINDEX@
+
+alarm
+~~~~~
++*alarm* 'seconds'+
+
+Delivers the +SIGALRM+ signal to the process after the given
+number of seconds. If the platform supports 'ualarm(3)' then
+the argument may be a floating point value. Otherwise it must
+be an integer.
+
+Note that unless a signal handler for +SIGALRM+ has been installed
+(see `signal`), the process will exit on this signal.
+
+alias
+~~~~~
++*alias* 'name args\...'+
+
+Creates a single word alias (command) for one or more words. For example,
+the following creates an alias for the command `info exists`.
+
+    alias e info exists
+    if {[e var]} {
+      ...
+    }
+
+`alias` returns +'name'+, allowing it to be used with `local`.
+
+See also `proc`, `curry`, `lambda`, `local`, `info alias`, `exists -alias`
+
+append
+~~~~~~
++*append* 'varName value ?value value ...?'+
+
+Append all of the +'value'+ arguments to the current value
+of variable +'varName'+.  If +'varName'+ doesn't exist,
+it is given a value equal to the concatenation of all the
++'value'+ arguments.
+
+This command provides an efficient way to build up long
+variables incrementally.
+For example, "`append a $b`" is much more efficient than
+"`set a $a$b`" if +$a+ is long.
+
+apply
+~~~~~~
++*apply* 'lambdaExpr ?arg1 arg2 \...?'+
+
+The command `apply` provides for anonymous procedure calls,
+similar to `lambda`, but without command name being created, even temporarily.
+
+The function  +'lambdaExpr'+ is a two element list +{args body}+
+or a three element list +{args body namespace}+. The first element
+args specifies the formal arguments, in the same form as the `proc` and `lambda` commands.
+
+array
+~~~~~
++*array* 'option arrayName ?arg\...?'+
+
+This command performs one of several operations on the
+variable given by +'arrayName'+.
+
+Note that in general, if the named array does not exist, the +'array'+ command behaves
+as though the array exists but is empty.
+
+The +'option'+ argument determines what action is carried out by the
+command.  The legal +'options'+ (which may be abbreviated) are:
+
++*array exists* 'arrayName'+::
+    Returns 1 if arrayName is an array variable, 0 if there is
+    no variable by that name.  This command is essentially
+    identical to `info exists`
+
++*array get* 'arrayName ?pattern?'+::
+    Returns a list containing pairs of elements. The first
+    element in each pair is the name of an element in arrayName
+    and the second element of each pair is the value of the
+    array element. The order of the pairs is undefined. If
+    pattern is not specified, then all of the elements of the
+    array are included in the result. If pattern is specified,
+    then only those elements whose names match pattern (using
+    the matching rules of string match) are included. If arrayName
+    isn't the name of an array variable, or if the array contains
+    no elements, then an empty list is returned.
+
++*array names* 'arrayName ?pattern?'+::
+    Returns a list containing the names of all of the elements
+    in the array that match pattern. If pattern is omitted then
+    the command returns all of the element names in the array.
+    If pattern is specified, then only those elements whose
+    names match pattern (using the matching rules of string
+    match) are included. If there are no (matching) elements
+    in the array, or if arrayName isn't the name of an array
+    variable, then an empty string is returned.
+
++*array set* 'arrayName list'+::
+    Sets the values of one or more elements in arrayName. list
+    must have a form like that returned by array get, consisting
+    of an even number of elements. Each odd-numbered element
+    in list is treated as an element name within arrayName, and
+    the following element in list is used as a new value for
+    that array element. If the variable arrayName does not
+    already exist and list is empty, arrayName is created with
+    an empty array value.
+
++*array size* 'arrayName'+::
+    Returns the number of elements in the array. If arrayName
+    isn't the name of an array then 0 is returned.
+
++*array unset* 'arrayName ?pattern?'+::
+    Unsets all of the elements in the array that match pattern
+    (using the matching rules of string match). If arrayName
+    isn't the name of an array variable or there are no matching
+    elements in the array, no error will be raised. If pattern
+    is omitted and arrayName is an array variable, then the
+    command unsets the entire array. The command always returns
+    an empty string.
+
+break
+~~~~~
++*break*+
+
+This command may be invoked only inside the body of a loop command
+such as `for` or `foreach` or `while`.  It returns a +JIM_BREAK+ code
+to signal the innermost containing loop command to return immediately.
+
+case
+~~~~
++*case* 'string' ?in? 'patList body ?patList body ...?'+
+
++*case* 'string' ?in? {'patList body ?patList body ...?'}+
+
+*Note* that the `switch` command should generally be preferred unless compatibility
+with Tcl 6.x is desired.
+
+Match +'string'+ against each of the +'patList'+ arguments
+in order.  If one matches, then evaluate the following +'body'+ argument
+by passing it recursively to the Tcl interpreter, and return the result
+of that evaluation.  Each +'patList'+ argument consists of a single
+pattern or list of patterns.  Each pattern may contain any of the wild-cards
+described under `string match`.
+
+If a +'patList'+ argument is +default+, the corresponding body will be
+evaluated if no +'patList'+ matches +'string'+.  If no +'patList'+ argument
+matches +'string'+ and no default is given, then the `case` command returns
+an empty string.
+
+Two syntaxes are provided.
+
+The first uses a separate argument for each of the patterns and commands;
+this form is convenient if substitutions are desired on some of the
+patterns or commands.
+
+The second form places all of the patterns and commands together into
+a single argument; the argument must have proper list structure, with
+the elements of the list being the patterns and commands.
+
+The second form makes it easy to construct multi-line case commands,
+since the braces around the whole list make it unnecessary to include a
+backslash at the end of each line.
+
+Since the +'patList'+ arguments are in braces in the second form,
+no command or variable substitutions are performed on them;  this makes
+the behaviour of the second form different than the first form in some
+cases.
+
+Below are some examples of `case` commands:
+
+    case abc in {a b} {format 1} default {format 2} a* {format 3}
+
+will return '3',
+
+    case a in {
+        {a b} {format 1}
+        default {format 2}
+        a* {format 3}
+    }
+
+will return '1', and
+
+    case xyz {
+        {a b}
+            {format 1}
+        default
+            {format 2}
+        a*
+            {format 3}
+    }
+
+will return '2'.
+
+catch
+~~~~~
++*catch* ?-?no?'code \...'? ?--? 'command ?resultVarName? ?optionsVarName?'+
+
+The `catch` command may be used to prevent errors from aborting
+command interpretation.  `catch` evaluates +'command'+, and returns a
++JIM_OK+ code, regardless of any errors that might occur while
+executing +'command'+ (with the possible exception of +JIM_SIGNAL+ -
+see below).
+
+The return value from `catch` is a decimal string giving the code
+returned by the Tcl interpreter after executing +'command'+.  This
+will be '0' (+JIM_OK+) if there were no errors in +'command'+; otherwise
+it will have a non-zero value corresponding to one of the exceptional
+return codes (see jim.h for the definitions of code values, or the
+`info returncodes` command).
+
+If the +'resultVarName'+ argument is given, then it gives the name
+of a variable; `catch` will set the value of the variable to the
+string returned from +'command'+ (either a result or an error message).
+
+If the +'optionsVarName'+ argument is given, then it gives the name
+of a variable; `catch` will set the value of the variable to a
+dictionary. For any return code other than +JIM_RETURN+, the value
+for the key +-code+ will be set to the return code. For +JIM_RETURN+
+it will be set to the code given in `return -code`. Additionally,
+for the return code +JIM_ERR+, the value of the key +-errorinfo+
+will contain the current stack trace (the same result as `info stacktrace`),
+the value of the key +-errorcode+ will contain the
+same value as the global variable $::errorCode, and the value of
+the key +-level+ will be the current return level (see `return -level`).
+This can be useful to rethrow an error:
+
+    if {[catch {...} msg opts]} {
+        ...maybe do something with the error...
+        incr opts(-level)
+        return {*}$opts $msg
+    }
+
+Normally `catch` will +'not'+ catch any of the codes +JIM_EXIT+, +JIM_EVAL+ or +JIM_SIGNAL+.
+The set of codes which will be caught may be modified by specifying the one more codes before
++'command'+.
+
+e.g. To catch +JIM_EXIT+ but not +JIM_BREAK+ or +JIM_CONTINUE+
+
+    catch -exit -nobreak -nocontinue -- { ... }
+
+The use of +--+ is optional. It signifies that no more return code options follow.
+
+Note that if a signal marked as `signal handle` is caught with `catch -signal`, the return value
+(stored in +'resultVarName'+) is name of the signal caught.
+
+cd
+~~
++*cd* 'dirName'+
+
+Change the current working directory to +'dirName'+.
+
+Returns an empty string.
+
+This command can potentially be disruptive to an application, so it may
+be removed in some applications.
+
+clock
+~~~~~
++*clock seconds*+::
+    Returns the current time as seconds since the epoch.
+
++*clock format* 'seconds' ?*-format* 'format?'+::
+    Format the given time (seconds since the epoch) according to the given
+    format. See strftime(3) for supported formats.
+    If no format is supplied, "%c" is used.
+
++*clock scan* 'str' *-format* 'format'+::
+    Scan the given time string using the given format string.
+    See strptime(3) for supported formats.
+
+close
+~~~~~
++*close* 'fileId'+
+
++'fileId' *close*+
+
+Closes the file given by +'fileId'+.
++'fileId'+ must be the return value from a previous invocation
+of the `open` command; after this command, it should not be
+used anymore.
+
+collect
+~~~~~~~
++*collect*+
+
+Normally reference garbage collection is automatically performed periodically.
+However it may be run immediately with the `collect` command.
+
+See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.
+
+concat
+~~~~~~
++*concat* 'arg ?arg \...?'+
+
+This command treats each argument as a list and concatenates them
+into a single list.  It permits any number of arguments.  For example,
+the command
+
+    concat a b {c d e} {f {g h}}
+
+will return
+
+    a b c d e f {g h}
+
+as its result.
+
+continue
+~~~~~~~~
++*continue*+
+
+This command may be invoked only inside the body of a loop command such
+as `for` or `foreach` or `while`.  It returns a  +JIM_CONTINUE+ code to
+signal the innermost containing loop command to skip the remainder of
+the loop's body but continue with the next iteration of the loop.
+
+curry
+~~~~~
++*alias* 'args\...'+
+
+Similar to `alias` except it creates an anonymous procedure (lambda) instead of
+a named procedure.
+
+the following creates a local, unnamed alias for the command `info exists`.
+
+    set e [local curry info exists]
+    if {[$e var]} {
+      ...
+    }
+
+`curry` returns the name of the procedure.
+
+See also `proc`, `alias`, `lambda`, `local`.
+
+dict
+~~~~
++*dict* 'option ?arg\...?'+
+
+Performs one of several operations on dictionary values.
+
+The +'option'+ argument determines what action is carried out by the
+command.  The legal +'options'+ are:
+
++*dict create* '?key value \...?'+::
+    Create and return a new dictionary value that contains each of
+    the key/value mappings listed as  arguments (keys and values
+    alternating, with each key being followed by its associated
+    value.)
+
++*dict exists* 'dictionary key ?key \...?'+::
+    Returns a boolean value indicating whether the given key (or path
+    of keys through a set of nested dictionaries) exists in the given
+    dictionary value.  This returns a true value exactly when `dict get`
+    on that path will succeed.
+
++*dict get* 'dictionary ?key \...?'+::
+    Given a dictionary value (first argument) and a key (second argument),
+    this will retrieve the value for that key. Where several keys are
+    supplied, the behaviour of the command shall be as if the result
+    of "`dict get $dictVal $key`" was passed as the first argument to
+    dict get with the remaining arguments as second (and possibly
+    subsequent) arguments. This facilitates lookups in nested dictionaries.
+    If no keys are provided, dict would return a list containing pairs
+    of elements in a man- ner similar to array get. That is, the first
+    element of each pair would be the key and the second element would
+    be the value for that key.  It is an error to attempt to retrieve
+    a value for a key that is not present in the dictionary.
+
++*dict keys* 'dictionary ?pattern?'+::
+    Returns a list of the keys in the dictionary.
+    If pattern is specified, then only those keys whose
+    names match +'pattern'+ (using the matching rules of string
+    match) are included.
+
++*dict merge* ?'dictionary \...'?+::
+    Return a dictionary that contains the contents of each of the
+    +'dictionary'+ arguments. Where two (or more) dictionaries
+    contain a mapping for the same key, the resulting dictionary
+    maps that key to the value according to the last dictionary on
+    the command line containing a mapping for that key.
+
++*dict set* 'dictionaryName key ?key \...? value'+::
+    This operation takes the +'name'+ of a variable containing a dictionary
+    value and places an updated dictionary value in that variable
+    containing a mapping from the given key to the given value. When
+    multiple keys are present, this operation creates or updates a chain
+    of nested dictionaries.
+
++*dict size* 'dictionary'+::
+    Return the number of key/value mappings in the given dictionary value.
+
++*dict unset* 'dictionaryName key ?key \...? value'+::
+    This operation (the companion to `dict set`) takes the name of a
+    variable containing a dictionary value and places an updated
+    dictionary value in that variable that does not contain a mapping
+    for the given key. Where multiple keys are present, this describes
+    a path through nested dictionaries to the mapping to remove. At
+    least one key must be specified, but the last key on the key-path
+    need not exist. All other components on the path must exist.
+
++*dict with* 'dictionaryName key ?key \...? script'+::
+    Execute the Tcl script in +'script'+ with the value for each
+    key in +'dictionaryName'+ mapped to a variable with the same
+    name. Where one or more keys are given, these indicate a chain
+    of nested dictionaries, with the innermost dictionary being the
+    one opened out for the execution of body. Making +'dictionaryName'+
+    unreadable will make the updates to the dictionary be discarded,
+    and this also happens if the contents of +'dictionaryName'+ are
+    adjusted so that the chain of dictionaries no longer exists.
+    The result of `dict with` is (unless some kind of error occurs)
+    the result of the evaluation of body.
+ ::
+    The variables are mapped in the scope enclosing the `dict with`;
+    it is recommended that this command only be used in a local
+    scope (procedure). Because of this, the variables set by
+    `dict with` will continue to exist after the command finishes (unless
+    explicitly unset). Note that changes to the contents of +'dictionaryName'+
+    only happen when +'script'+ terminates.
+
++*dict for, values, incr, append, lappend, update, info, replace*+ to be documented...
+
+env
+~~~
++*env* '?name? ?default?'+
+
+If +'name'+ is supplied, returns the value of +'name'+ from the initial
+environment (see getenv(3)). An error is returned if +'name'+ does not
+exist in the environment, unless +'default'+ is supplied - in which case
+that value is returned instead.
+
+If no arguments are supplied, returns a list of all environment variables
+and their values as +{name value \...}+
+
+See also the global variable +::env+
+
+eof
+~~~
++*eof* 'fileId'+
+
++'fileId' *eof*+
+
+Returns 1 if an end-of-file condition has occurred on +'fileId'+,
+0 otherwise.
+
++'fileId'+ must have been the return value from a previous call to `open`,
+or it may be +stdin+, +stdout+, or +stderr+ to refer to one of the
+standard I/O channels.
+
+error
+~~~~~
++*error* 'message ?stacktrace?'+
+
+Returns a +JIM_ERR+ code, which causes command interpretation to be
+unwound.  +'message'+ is a string that is returned to the application
+to indicate what went wrong.
+
+If the +'stacktrace'+ argument is provided and is non-empty,
+it is used to initialize the stacktrace.
+
+This feature is most useful in conjunction with the `catch` command:
+if a caught error cannot be handled successfully, +'stacktrace'+ can be used
+to return a stack trace reflecting the original point of occurrence
+of the error:
+
+    catch {...} errMsg
+    ...
+    error $errMsg [info stacktrace]
+
+See also `errorInfo`, `info stacktrace`, `catch` and `return`
+
+errorInfo
+~~~~~~~~~
++*errorInfo* 'error ?stacktrace?'+
+
+Returns a human-readable representation of the given error message and stack trace.
+Typical usage is:
+
+    if {[catch {...} error]} {
+        puts stderr [errorInfo $error [info stacktrace]]
+        exit 1
+    }
+
+See also `error`.
+
+eval
+~~~~
++*eval* 'arg ?arg\...?'+
+
+`eval` takes one or more arguments, which together comprise a Tcl
+command (or collection of Tcl commands separated by newlines in the
+usual way).  `eval` concatenates all its arguments in the same
+fashion as the `concat` command, passes the concatenated string to the
+Tcl interpreter recursively, and returns the result of that
+evaluation (or any error generated by it).
+
+exec
+~~~~
++*exec* 'arg ?arg\...?'+
+
+This command treats its arguments as the specification
+of one or more UNIX commands to execute as subprocesses.
+The commands take the form of a standard shell pipeline;
++|+ arguments separate commands in the
+pipeline and cause standard output of the preceding command
+to be piped into standard input of the next command (or +|&+ for
+both standard output and standard error).
+
+Under normal conditions the result of the `exec` command
+consists of the standard output produced by the last command
+in the pipeline.
+
+If any of the commands in the pipeline exit abnormally or
+are killed or suspended, then `exec` will return an error
+and the error message will include the pipeline's output followed by
+error messages describing the abnormal terminations.
+
+If any of the commands writes to its standard error file,
+then `exec` will return an error, and the error message
+will include the pipeline's output, followed by messages
+about abnormal terminations (if any), followed by the standard error
+output.
+
+If the last character of the result or error message
+is a newline then that character is deleted from the result
+or error message for consistency with normal
+Tcl return values.
+
+An +'arg'+ may have one of the following special forms:
+
++>filename+::
+    The standard output of the last command in the pipeline
+    is redirected to the file.  In this situation `exec`
+    will normally return an empty string.
+
++>>filename+::
+    As above, but append to the file.
+
++>@fileId+::
+    The standard output of the last command in the pipeline is
+    redirected to the given (writable) file descriptor (e.g. stdout,
+    stderr, or the result of `open`). In this situation `exec`
+    will normally return an empty string.
+
++2>filename+::
+    The standard error of the last command in the pipeline
+    is redirected to the file.
+
++2>>filename+::
+    As above, but append to the file.
+
++2>@fileId+::
+    The standard error of the last command in the pipeline is
+    redirected to the given (writable) file descriptor.
+
++2>@1+::
+    The standard error of the last command in the pipeline is
+    redirected to the same file descriptor as the standard output.
+
++>&filename+::
+    Both the standard output and standard error of the last command
+    in the pipeline is redirected to the file.
+
++>>&filename+::
+    As above, but append to the file.
+
++<filename+::
+    The standard input of the first command in the pipeline
+    is taken from the file.
+
++<<string+::
+    The standard input of the first command is taken as the
+    given immediate value.
+
++<@fileId+::
+    The standard input of the first command in the pipeline
+    is taken from the given (readable) file descriptor.
+
+If there is no redirection of standard input, standard error
+or standard output, these are connected to the corresponding
+input or output of the application.
+
+If the last +'arg'+ is +&+ then the command will be
+executed in background.
+In this case the standard output from the last command
+in the pipeline will
+go to the application's standard output unless
+redirected in the command, and error output from all
+the commands in the pipeline will go to the application's
+standard error file. The return value of exec in this case
+is a list of process ids (pids) in the pipeline.
+
+Each +'arg'+ becomes one word for a command, except for
++|+, +<+, +<<+, +>+, and +&+ arguments, and the
+arguments that follow +<+, +<<+, and +>+.
+
+The first word in each command is taken as the command name;
+the directories in the PATH environment variable are searched for
+an executable by the given name.
+
+No `glob` expansion or other shell-like substitutions
+are performed on the arguments to commands.
+
+If the command fails, the global $::errorCode (and the -errorcode
+option in `catch`) will be set to a list, as follows:
+
++*CHILDKILLED* 'pid sigName msg'+::
+        This format is used when a child process has been killed
+        because of a signal. The pid element will be the process's
+        identifier (in decimal). The sigName element will be the
+        symbolic name of the signal that caused the process to
+        terminate; it will be one of the names from the include
+        file signal.h, such as SIGPIPE. The msg element will be a
+        short human-readable message describing the signal, such
+        as "write on pipe with no readers" for SIGPIPE.
+
++*CHILDSUSP* 'pid sigName msg'+::
+        This format is used when a child process has been suspended
+        because of a signal. The pid element will be the process's
+        identifier, in decimal. The sigName element will be the
+        symbolic name of the signal that caused the process to
+        suspend; this will be one of the names from the include
+        file signal.h, such as SIGTTIN. The msg element will be a
+        short human-readable message describing the signal, such
+        as "background tty read" for SIGTTIN.
+
++*CHILDSTATUS* 'pid code'+::
+        This format is used when a child process has exited with a
+        non-zero exit status. The pid element will be the process's
+        identifier (in decimal) and the code element will be the
+        exit code returned by the process (also in decimal).
+
+The environment for the executed command is set from $::env (unless
+this variable is unset, in which case the original environment is used).
+
+exists
+~~~~~~
++*exists ?-var|-proc|-command|-alias?* 'name'+
+
+Checks the existence of the given variable, procedure, command
+or alias respectively and returns 1 if it exists or 0 if not.  This command
+provides a more simplified/convenient version of `info exists`,
+`info procs` and `info commands`.
+
+If the type is omitted, a type of '-var' is used. The type may be abbreviated.
+
+exit
+~~~~
++*exit* '?returnCode?'+
+
+Terminate the process, returning +'returnCode'+ to the
+parent as the exit status.
+
+If +'returnCode'+ isn't specified then it defaults
+to 0.
+
+Note that exit can be caught with `catch`.
+
+expr
+~~~~
++*expr* 'arg'+
+
+Calls the expression processor to evaluate +'arg'+, and returns
+the result as a string.  See the section EXPRESSIONS above.
+
+Note that Jim supports a shorthand syntax for `expr` as +$(\...)+
+The following two are identical.
+
+  set x [expr {3 * 2 + 1}]
+  set x $(3 * 2 + 1)
+
+file
+~~~~
++*file* 'option name ?arg\...?'+
+
+Operate on a file or a file name.  +'name'+ is the name of a file.
+
++'option'+ indicates what to do with the file name.  Any unique
+abbreviation for +'option'+ is acceptable.  The valid options are:
+
++*file atime* 'name'+::
+    Return a decimal string giving the time at which file +'name'+
+    was last accessed.  The time is measured in the standard UNIX
+    fashion as seconds from a fixed starting time (often January 1, 1970).
+    If the file doesn't exist or its access time cannot be queried then an
+    error is generated.
+
++*file copy ?-force?* 'source target'+::
+    Copies file +'source'+ to file +'target'+. The source file must exist.
+    The target file must not exist, unless +-force+ is specified.
+
++*file delete ?-force?* 'name\...'+::
+    Deletes file or directory +'name'+. If the file or directory doesn't exist, nothing happens.
+    If it can't be deleted, an error is generated. Non-empty directories will not be deleted
+    unless the +-force+ options is given. In this case no errors will be generated, even
+    if the file/directory can't be deleted.
+
++*file dirname* 'name'+::
+    Return all of the characters in +'name'+ up to but not including
+    the last slash character.  If there are no slashes in +'name'+
+    then return +.+ (a single dot).  If the last slash in +'name'+ is its first
+    character, then return +/+.
+
++*file executable* 'name'+::
+    Return '1' if file +'name'+ is executable by
+    the current user, '0' otherwise.
+
++*file exists* 'name'+::
+    Return '1' if file +'name'+ exists and the current user has
+    search privileges for the directories leading to it, '0' otherwise.
+
++*file extension* 'name'+::
+    Return all of the characters in +'name'+ after and including the
+    last dot in +'name'+.  If there is no dot in +'name'+ then return
+    the empty string.
+
++*file isdirectory* 'name'+::
+    Return '1' if file +'name'+ is a directory,
+    '0' otherwise.
+
++*file isfile* 'name'+::
+    Return '1' if file +'name'+ is a regular file,
+    '0' otherwise.
+
++*file join* 'arg\...'+::
+    Joins multiple path components. Note that if any components is
+    an absolute path, the preceding components are ignored.
+    Thus +"`file` join /tmp /root"+ returns +"/root"+.
+
++*file lstat* 'name varName'+::
+    Same as 'stat' option (see below) except uses the +'lstat'+
+    kernel call instead of +'stat'+.  This means that if +'name'+
+    refers to a symbolic link the information returned in +'varName'+
+    is for the link rather than the file it refers to.  On systems that
+    don't support symbolic links this option behaves exactly the same
+    as the 'stat' option.
+
++*file mkdir* 'dir1 ?dir2\...?'+::
+    Creates each directory specified. For each pathname +'dir'+ specified,
+    this command will create all non-existing parent directories
+    as well as +'dir'+ itself. If an existing directory is specified,
+    then no action is taken and no error is returned. Trying to
+    overwrite an existing file with a directory will result in an
+    error.  Arguments are processed in the order specified, halting
+    at the first error, if any.
+
++*file mtime* 'name ?time?'+::
+    Return a decimal string giving the time at which file +'name'+
+    was last modified.  The time is measured in the standard UNIX
+    fashion as seconds from a fixed starting time (often January 1, 1970).
+    If the file doesn't exist or its modified time cannot be queried then an
+    error is generated. If +'time'+ is given, sets the modification time
+    of the file to the given value.
+
++*file normalize* 'name'+::
+    Return the normalized path of +'name'+. See 'realpath(3)'.
+
++*file owned* 'name'+::
+    Return '1' if file +'name'+ is owned by the current user,
+    '0' otherwise.
+
++*file readable* 'name'+::
+    Return '1' if file +'name'+ is readable by
+    the current user, '0' otherwise.
+
++*file readlink* 'name'+::
+    Returns the value of the symbolic link given by +'name'+ (i.e. the
+    name of the file it points to).  If
+    +'name'+ isn't a symbolic link or its value cannot be read, then
+    an error is returned.  On systems that don't support symbolic links
+    this option is undefined.
+
++*file rename* 'oldname' 'newname'+::
+    Renames the file from the old name to the new name.
+
++*file rootname* 'name'+::
+    Return all of the characters in +'name'+ up to but not including
+    the last '.' character in the name.  If +'name'+ doesn't contain
+    a dot, then return +'name'+.
+
++*file size* 'name'+::
+    Return a decimal string giving the size of file +'name'+ in bytes.
+    If the file doesn't exist or its size cannot be queried then an
+    error is generated.
+
++*file stat* 'name ?varName?'+::
+    Invoke the 'stat' kernel call on +'name'+, and return the result
+       as a dictionary with the following keys: 'atime',
+    'ctime', 'dev', 'gid', 'ino', 'mode', 'mtime',
+    'nlink', 'size', 'type', 'uid'.
+    Each element except 'type' is a decimal string with the value of
+    the corresponding field from the 'stat' return structure; see the
+    manual entry for 'stat' for details on the meanings of the values.
+    The 'type' element gives the type of the file in the same form
+    returned by the command `file type`.
+       If +'varName'+ is specified, it is taken to be the name of an array
+       variable and the values are also stored into the array.
+
++*file tail* 'name'+::
+    Return all of the characters in +'name'+ after the last slash.
+    If +'name'+ contains no slashes then return +'name'+.
+
++*file tempfile* '?template?'+::
+    Creates and returns the name of a unique temporary file. If +'template'+ is omitted, a
+    default template will be used to place the file in /tmp. See 'mkstemp(3)' for
+    the format of the template and security concerns.
+
++*file type* 'name'+::
+    Returns a string giving the type of file +'name'+, which will be
+    one of +file+, +directory+, +characterSpecial+,
+    +blockSpecial+, +fifo+, +link+, or +socket+.
+
++*file writable* 'name'+::
+    Return '1' if file +'name'+ is writable by
+    the current user, '0' otherwise.
+
+The `file` commands that return 0/1 results are often used in
+conditional or looping commands, for example:
+
+    if {![file exists foo]} {
+        error {bad file name}
+    } else {
+        ...
+    }
+
+finalize
+~~~~~~~~
++*finalize* 'reference ?command?'+
+
+If +'command'+ is omitted, returns the finalizer command for the given reference.
+
+Otherwise, sets a new finalizer command for the given reference. +'command'+ may be
+the empty string to remove the current finalizer.
+
+The reference must be a valid reference create with the `ref`
+command.
+
+See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.
+
+flush
+~~~~~
++*flush* 'fileId'+
+
++'fileId' *flush*+
+
+Flushes any output that has been buffered for +'fileId'+.  +'fileId'+ must
+have been the return value from a previous call to `open`, or it may be
++stdout+ or +stderr+ to access one of the standard I/O streams; it must
+refer to a file that was opened for writing.  This command returns an
+empty string.
+
+for
+~~~
++*for* 'start test next body'+
+
+`for` is a looping command, similar in structure to the C `for` statement.
+The +'start'+, +'next'+, and +'body'+ arguments must be Tcl command strings,
+and +'test'+ is an expression string.
+
+The `for` command first invokes the Tcl interpreter to execute +'start'+.
+Then it repeatedly evaluates +'test'+ as an expression; if the result is
+non-zero it invokes the Tcl interpreter on +'body'+, then invokes the Tcl
+interpreter on +'next'+, then repeats the loop.  The command terminates
+when +'test'+ evaluates to 0.
+
+If a `continue` command is invoked within +'body'+ then any remaining
+commands in the current execution of +'body'+ are skipped; processing
+continues by invoking the Tcl interpreter on +'next'+, then evaluating
++'test'+, and so on.
+
+If a `break` command is invoked within +'body'+ or +'next'+, then the `for`
+command will return immediately.
+
+The operation of `break` and `continue` are similar to the corresponding
+statements in C.
+
+`for` returns an empty string.
+
+foreach
+~~~~~~~
++*foreach* 'varName list body'+
+
++*foreach* 'varList list ?varList2 list2 \...? body'+
+
+In this command, +'varName'+ is the name of a variable, +'list'+
+is a list of values to assign to +'varName'+, and +'body'+ is a
+collection of Tcl commands.
+
+For each field in +'list'+ (in order from left to right), `foreach` assigns
+the contents of the field to +'varName'+ (as if the `lindex` command
+had been used to extract the field), then calls the Tcl interpreter to
+execute +'body'+.
+
+If instead of being a simple name, +'varList'+ is used, multiple assignments
+are made each time through the loop, one for each element of +'varList'+.
+
+For example, if there are two elements in +'varList'+ and six elements in
+the list, the loop will be executed three times.
+
+If the length of the list doesn't evenly divide by the number of elements
+in +'varList'+, the value of the remaining variables in the last iteration
+of the loop are undefined.
+
+The `break` and `continue` statements may be invoked inside +'body'+,
+with the same effect as in the `for` command.
+
+`foreach` returns an empty string.
+
+format
+~~~~~~
++*format* 'formatString ?arg \...?'+
+
+This command generates a formatted string in the same way as the
+C 'sprintf' procedure (it uses 'sprintf' in its
+implementation).  +'formatString'+ indicates how to format
+the result, using +%+ fields as in 'sprintf', and the additional
+arguments, if any, provide values to be substituted into the result.
+
+All of the 'sprintf' options are valid; see the 'sprintf'
+man page for details.  Each +'arg'+ must match the expected type
+from the +%+ field in +'formatString'+; the `format` command
+converts each argument to the correct type (floating, integer, etc.)
+before passing it to 'sprintf' for formatting.
+
+The only unusual conversion is for +%c+; in this case the argument
+must be a decimal string, which will then be converted to the corresponding
+ASCII (or UTF-8) character value.
+
+In addition, Jim Tcl provides basic support for conversion to binary with +%b+.
+
+`format` does backslash substitution on its +'formatString'+
+argument, so backslash sequences in +'formatString'+ will be handled
+correctly even if the argument is in braces.
+
+The return value from `format` is the formatted string.
+
+getref
+~~~~~~
++*getref* 'reference'+
+
+Returns the string associated with +'reference'+. The reference must
+be a valid reference create with the `ref` command.
+
+See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.
+
+gets
+~~~~
++*gets* 'fileId ?varName?'+
+
++'fileId' *gets* '?varName?'+
+
+Reads the next line from the file given by +'fileId'+ and discards
+the terminating newline character.
+
+If +'varName'+ is specified, then the line is placed in the variable
+by that name and the return value is a count of the number of characters
+read (not including the newline).
+
+If the end of the file is reached before reading
+any characters then -1 is returned and +'varName'+ is set to an
+empty string.
+
+If +'varName'+ is not specified then the return value will be
+the line (minus the newline character) or an empty string if
+the end of the file is reached before reading any characters.
+
+An empty string will also be returned if a line contains no characters
+except the newline, so `eof` may have to be used to determine
+what really happened.
+
+If the last character in the file is not a newline character, then
+`gets` behaves as if there were an additional newline character
+at the end of the file.
+
++'fileId'+ must be +stdin+ or the return value from a previous
+call to `open`; it must refer to a file that was opened
+for reading.
+
+glob
+~~~~
++*glob* ?*-nocomplain*? ?*-directory* 'dir'? ?*--*? 'pattern ?pattern \...?'+
+
+This command performs filename globbing, using csh rules.  The returned
+value from `glob` is the list of expanded filenames.
+
+If +-nocomplain+ is specified as the first argument then an empty
+list may be returned;  otherwise an error is returned if the expanded
+list is empty.  The +-nocomplain+ argument must be provided
+exactly: an abbreviation will not be accepted.
+
+If +-directory+ is given, the +'dir'+ is understood to contain a
+directory name to search in. This allows globbing inside directories
+whose names may contain glob-sensitive characters. The returned names
+are specified relative to this directory.
+
+global
+~~~~~~
+
++*global* 'varName ?varName \...?'+
+
+This command is ignored unless a Tcl procedure is being interpreted.
+If so, then it declares each given +'varName'+ to be a global variable
+rather than a local one.  For the duration of the current procedure
+(and only while executing in the current procedure), any reference to
++'varName'+ will be bound to a global variable instead
+of a local one.
+
+An alternative to using `global` is to use the +::+ prefix
+to explicitly name a variable in the global scope.
+
+if
+~~
++*if* 'expr1' ?*then*? 'body1' *elseif* 'expr2' ?*then*? 'body2' *elseif* \... ?*else*? ?'bodyN'?+
+
+The `if` command evaluates +'expr1'+ as an expression (in the same way
+that `expr` evaluates its argument).  The value of the expression must
+be numeric; if it is non-zero then +'body1'+ is executed by passing it to
+the Tcl interpreter.
+
+Otherwise +'expr2'+ is evaluated as an expression and if it is non-zero
+then +'body2'+ is executed, and so on.
+
+If none of the expressions evaluates to non-zero then +'bodyN'+ is executed.
+
+The +then+ and +else+ arguments are optional "noise words" to make the
+command easier to read.
+
+There may be any number of +elseif+ clauses, including zero.  +'bodyN'+
+may also be omitted as long as +else+ is omitted too.
+
+The return value from the command is the result of the body script that
+was executed, or an empty string if none of the expressions was non-zero
+and there was no +'bodyN'+.
+
+incr
+~~~~
++*incr* 'varName ?increment?'+
+
+Increment the value stored in the variable whose name is +'varName'+.
+The value of the variable must be integral.
+
+If +'increment'+ is supplied then its value (which must be an
+integer) is added to the value of variable +'varName'+;  otherwise
+1 is added to +'varName'+.
+
+The new value is stored as a decimal string in variable +'varName'+
+and also returned as result.
+
+If the variable does not exist, the variable is implicitly created
+and set to +0+ first.
+
+info
+~~~~
+
++*info* 'option ?arg\...?'+::
+
+Provide information about various internals to the Tcl interpreter.
+The legal +'option'+'s (which may be abbreviated) are:
+
++*info args* 'procname'+::
+    Returns a list containing the names of the arguments to procedure
+    +'procname'+, in order.  +'procname'+ must be the name of a
+    Tcl command procedure.
+
++*info alias* 'command'+::
+    +'command'+ must be an alias created with `alias`. In which case the target
+    command and arguments, as passed to `alias` are returned. See `exists -alias`
+
++*info body* 'procname'+::
+    Returns the body of procedure +'procname'+.  +'procname'+ must be
+    the name of a Tcl command procedure.
+
++*info channels*+::
+    Returns a list of all open file handles from `open` or `socket`
+
++*info commands* ?'pattern'?+::
+    If +'pattern'+ isn't specified, returns a list of names of all the
+    Tcl commands, including both the built-in commands written in C and
+    the command procedures defined using the `proc` command.
+    If +'pattern'+ is specified, only those names matching +'pattern'+
+    are returned.  Matching is determined using the same rules as for
+    `string match`.
+
++*info complete* 'command' ?'missing'?+::
+    Returns 1 if +'command'+ is a complete Tcl command in the sense of
+    having no unclosed quotes, braces, brackets or array element names,
+    If the command doesn't appear to be complete then 0 is returned.
+    This command is typically used in line-oriented input environments
+    to allow users to type in commands that span multiple lines;  if the
+    command isn't complete, the script can delay evaluating it until additional
+    lines have been typed to complete the command. If +'varName'+ is specified, the
+    missing character is stored in the variable with that name.
+
++*info exists* 'varName'+::
+    Returns '1' if the variable named +'varName'+ exists in the
+    current context (either as a global or local variable), returns '0'
+    otherwise.
+
++*info frame* ?'number'?+::
+    If +'number'+ is not specified, this command returns a number
+    which is the same result as `info level` - the current stack frame level.
+    If +'number'+ is specified, then the result is a list consisting of the procedure,
+    filename and line number for the procedure call at level +'number'+ on the stack.
+    If +'number'+ is positive then it selects a particular stack level (1 refers
+    to the top-most active procedure, 2 to the procedure it called, and
+    so on); otherwise it gives a level relative to the current level
+    (0 refers to the current procedure, -1 to its caller, and so on).
+    The level has an identical meaning to `info level`.
+
++*info globals* ?'pattern'?+::
+    If +'pattern'+ isn't specified, returns a list of all the names
+    of currently-defined global variables.
+    If +'pattern'+ is specified, only those names matching +'pattern'+
+    are returned.  Matching is determined using the same rules as for
+    `string match`.
+
++*info hostname*+::
+    An alias for `os.gethostname` for compatibility with Tcl 6.x
+
++*info level* ?'number'?+::
+    If +'number'+ is not specified, this command returns a number
+    giving the stack level of the invoking procedure, or 0 if the
+    command is invoked at top-level.  If +'number'+ is specified,
+    then the result is a list consisting of the name and arguments for the
+    procedure call at level +'number'+ on the stack.  If +'number'+
+    is positive then it selects a particular stack level (1 refers
+    to the top-most active procedure, 2 to the procedure it called, and
+    so on); otherwise it gives a level relative to the current level
+    (0 refers to the current procedure, -1 to its caller, and so on).
+    See the `uplevel` command for more information on what stack
+    levels mean.
+
++*info locals* ?'pattern'?+::
+    If +'pattern'+ isn't specified, returns a list of all the names
+    of currently-defined local variables, including arguments to the
+    current procedure, if any.  Variables defined with the `global`
+    and `upvar` commands will not be returned.  If +'pattern'+ is
+    specified, only those names matching +'pattern'+ are returned.
+    Matching is determined using the same rules as for `string match`.
+
++*info nameofexecutable*+::
+    Returns the name of the binary file from which the application
+    was invoked. A full path will be returned, unless the path
+    can't be determined, in which case the empty string will be returned.
+
++*info procs* ?'pattern'?+::
+    If +'pattern'+ isn't specified, returns a list of all the
+    names of Tcl command procedures.
+    If +'pattern'+ is specified, only those names matching +'pattern'+
+    are returned.  Matching is determined using the same rules as for
+    `string match`.
+
++*info references*+::
+    Returns a list of all references which have not yet been garbage
+    collected.
+
++*info returncodes* ?'code'?+::
+    Returns a list representing the mapping of standard return codes
+    to names. e.g. +{0 ok 1 error 2 return \...}+. If a code is given,
+    instead returns the name for the given code.
+
++*info script*+::
+    If a Tcl script file is currently being evaluated (i.e. there is a
+    call to 'Jim_EvalFile' active or there is an active invocation
+    of the `source` command), then this command returns the name
+    of the innermost file being processed.  Otherwise the command returns an
+    empty string.
+
++*info source* 'script'+::
+    Returns the original source location of the given script as a list of
+    +{filename linenumber}+. If the source location can't be determined, the
+    list +{{} 0}+ is returned.
+
++*info stacktrace*+::
+    After an error is caught with `catch`, returns the stack trace as a list
+    of +{procedure filename line \...}+.
+
++*info statics* 'procname'+::
+    Returns a dictionary of the static variables of procedure
+    +'procname'+.  +'procname'+ must be the name of a Tcl command
+    procedure. An empty dictionary is returned if the procedure has
+    no static variables.
+
++*info version*+::
+    Returns the version number for this version of Jim in the form +*x.yy*+.
+
++*info vars* ?'pattern'?+::
+    If +'pattern'+ isn't specified,
+    returns a list of all the names of currently-visible variables, including
+    both locals and currently-visible globals.
+    If +'pattern'+ is specified, only those names matching +'pattern'+
+    are returned.  Matching is determined using the same rules as for
+    `string match`.
+
+join
+~~~~
++*join* 'list ?joinString?'+
+
+The +'list'+ argument must be a valid Tcl list.  This command returns the
+string formed by joining all of the elements of +'list'+ together with
++'joinString'+ separating each adjacent pair of elements.
+
+The +'joinString'+ argument defaults to a space character.
+
+kill
+~~~~
++*kill* ?'SIG'|*-0*? 'pid'+
+
+Sends the given signal to the process identified by +'pid'+.
+
+The signal may be specified by name or number in one of the following forms:
+
+* +TERM+
+* +SIGTERM+
+* +-TERM+
+* +15+
+* +-15+
+
+The signal name may be in either upper or lower case.
+
+The special signal name +-0+ simply checks that a signal +'could'+ be sent.
+
+If no signal is specified, SIGTERM is used.
+
+An error is raised if the signal could not be delivered.
+
+lambda
+~~~~~~
++*lambda* 'args ?statics? body'+
+
+The `lambda` command is identical to `proc`, except rather than
+creating a named procedure, it creates an anonymous procedure and returns
+the name of the procedure.
+
+See `proc` and GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.
+
+lappend
+~~~~~~~
++*lappend* 'varName value ?value value \...?'+
+
+Treat the variable given by +'varName'+ as a list and append each of
+the +'value'+ arguments to that list as a separate element, with spaces
+between elements.
+
+If +'varName'+ doesn't exist, it is created as a list with elements given
+by the +'value'+ arguments. `lappend` is similar to `append` except that
+each +'value'+ is appended as a list element rather than raw text.
+
+This command provides a relatively efficient way to build up large lists.
+For example,
+
+    lappend a $b
+
+is much more efficient than
+
+    set a [concat $a [list $b]]
+
+when +$a+ is long.
+
+lassign
+~~~~~~~
++*lassign* 'list varName ?varName \...?'+
+
+This command treats the value +'list'+ as a list and assigns successive elements from that list to
+the variables given by the +'varName'+ arguments in order. If there are more variable names than
+list elements, the remaining variables are set to the empty string. If there are more list ele-
+ments than variables, a list of unassigned elements is returned.
+
+    jim> lassign {1 2 3} a b; puts a=$a,b=$b
+    3
+    a=1,b=2
+
+local
+~~~~~
++*local* 'cmd ?arg\...?'+
+
+First, `local` evaluates +'cmd'+ with the given arguments. The return value must
+be the name of an existing command, which is marked as having local scope.
+This means that when the current procedure exits, the specified
+command is deleted. This can be useful with `lambda`, local procedures or
+to automatically close a filehandle.
+
+In addition, if a command already exists with the same name,
+the existing command will be kept rather than deleted, and may be called
+via `upcall`. The previous command will be restored when the current
+procedure exits. See `upcall` for more details.
+
+In this example, a local procedure is created. Note that the procedure
+continues to have global scope while it is active.
+
+    proc outer {} {
+      # proc ... returns "inner" which is marked local
+      local proc inner {} {
+        # will be deleted when 'outer' exits
+      }
+
+      inner
+      ...
+    }
+
+In this example, the lambda is deleted at the end of the procedure rather
+than waiting until garbage collection.
+
+    proc outer {} {
+      set x [lambda inner {args} {
+        # will be deleted when 'outer' exits
+      }]
+      # Use 'function' here which simply returns $x
+      local function $x
+
+      $x ...
+      ...
+    }
+
+loop
+~~~~
++*loop* 'var first limit ?incr? body'+
+
+Similar to `for` except simpler and possibly more efficient.
+With a positive increment, equivalent to:
+
+  for {set var $first} {$var < $limit} {incr var $incr} $body
+
+If +'incr'+ is not specified, 1 is used.
+Note that setting the loop variable inside the loop does not
+affect the loop count.
+
+lindex
+~~~~~~
++*lindex* 'list ?index ...?'+
+
+Treats +'list'+ as a Tcl list and returns element +'index'+ from it
+(0 refers to the first element of the list).
+See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'index'+.
+
+In extracting the element, +'lindex'+ observes the same rules concerning
+braces and quotes and backslashes as the Tcl command interpreter; however,
+variable substitution and command substitution do not occur.
+
+If no index values are given, simply returns +'list'+
+
+If +'index'+ is negative or greater than or equal to the number of elements
+in +'list'+, then an empty string is returned.
+
+If additional index arguments are supplied, then each argument is
+used in turn to select an element from the previous indexing
+operation, allowing the script to select elements from sublists.
+
+linsert
+~~~~~~~
++*linsert* 'list index element ?element element \...?'+
+
+This command produces a new list from +'list'+ by inserting all
+of the +'element'+ arguments just before the element +'index'+
+of +'list'+. Each +'element'+ argument will become
+a separate element of the new list. If +'index'+ is less than
+or equal to zero, then the new elements are inserted at the
+beginning of the list. If +'index'+ is greater than or equal
+to the number of elements in the list, then the new elements are
+appended to the list.
+
+See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'index'+.
+
+list
+~~~~
+
++*list* 'arg ?arg \...?'+
+
+This command returns a list comprised of all the arguments, +'arg'+. Braces
+and backslashes get added as necessary, so that the `lindex` command
+may be used on the result to re-extract the original arguments, and also
+so that `eval` may be used to execute the resulting list, with
++'arg1'+ comprising the command's name and the other args comprising
+its arguments. `list` produces slightly different results than
+`concat`:  `concat` removes one level of grouping before forming
+the list, while `list` works directly from the original arguments.
+For example, the command
+
+    list a b {c d e} {f {g h}}
+
+will return
+
+    a b {c d e} {f {g h}}
+
+while `concat` with the same arguments will return
+
+    a b c d e f {g h}
+
+llength
+~~~~~~~
++*llength* 'list'+
+
+Treats +'list'+ as a list and returns a decimal string giving
+the number of elements in it.
+
+lset
+~~~~
++*lset* 'varName ?index ..? newValue'+
+
+Sets an element in a list.
+
+The `lset` command accepts a parameter, +'varName'+, which it interprets
+as the name of a variable containing a Tcl list. It also accepts
+zero or more indices into the list. Finally, it accepts a new value
+for an element of varName. If no indices are presented, the command
+takes the form:
+
+    lset varName newValue
+
+In this case, newValue replaces the old value of the variable
+varName.
+
+When presented with a single index, the `lset` command
+treats the content of the varName variable as a Tcl list. It addresses
+the index'th element in it (0 refers to the first element of the
+list). When interpreting the list, `lset` observes the same rules
+concerning braces and quotes and backslashes as the Tcl command
+interpreter; however, variable substitution and command substitution
+do not occur. The command constructs a new list in which the
+designated element is replaced with newValue. This new list is
+stored in the variable varName, and is also the return value from
+the `lset` command.
+
+If index is negative or greater than or equal to the number of
+elements in $varName, then an error occurs.
+
+See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'index'+.
+
+If additional index arguments are supplied, then each argument is
+used in turn to address an element within a sublist designated by
+the previous indexing operation, allowing the script to alter
+elements in sublists. The command,
+
+    lset a 1 2 newValue
+
+replaces element 2 of sublist 1 with +'newValue'+.
+
+The integer appearing in each index argument must be greater than
+or equal to zero. The integer appearing in each index argument must
+be strictly less than the length of the corresponding list. In other
+words, the `lset` command cannot change the size of a list. If an
+index is outside the permitted range, an error is reported.
+
+lmap
+~~~~
+
++*lmap* 'varName list body'+
+
++*lmap* 'varList list ?varList2 list2 \...? body'+
+
+`lmap` is a "collecting" `foreach` which returns a list of its results.
+
+For example:
+
+    jim> lmap i {1 2 3 4 5} {expr $i*$i}
+    1 4 9 16 25
+    jim> lmap a {1 2 3} b {A B C} {list $a $b}
+    {1 A} {2 B} {3 C}
+
+If the body invokes `continue`, no value is added for this iteration.
+If the body invokes `break`, the loop ends and no more values are added.
+
+load
+~~~~
++*load* 'filename'+
+
+Loads the dynamic extension, +'filename'+. Generally the filename should have
+the extension +.so+. The initialisation function for the module must be based
+on the name of the file. For example loading +hwaccess.so+ will invoke
+the initialisation function, +Jim_hwaccessInit+. Normally the `load` command
+should not be used directly. Instead it is invoked automatically by `package require`.
+
+lrange
+~~~~~~
++*lrange* 'list first last'+
+
++'list'+ must be a valid Tcl list. This command will return a new
+list consisting of elements +'first'+ through +'last'+, inclusive.
+
+See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'first'+ and +'last'+.
+
+If +'last'+ is greater than or equal to the number of elements
+in the list, then it is treated as if it were +end+.
+
+If +'first'+ is greater than +'last'+ then an empty string
+is returned.
+
+Note: +"`lrange` 'list first first'"+ does not always produce the
+same result as +"`lindex` 'list first'"+ (although it often does
+for simple fields that aren't enclosed in braces); it does, however,
+produce exactly the same results as +"`list` [`lindex` 'list first']"+
+
+lreplace
+~~~~~~~~
+
++*lreplace* 'list first last ?element element \...?'+
+
+Returns a new list formed by replacing one or more elements of
++'list'+ with the +'element'+ arguments.
+
++'first'+ gives the index in +'list'+ of the first element
+to be replaced.
+
+If +'first'+ is less than zero then it refers to the first
+element of +'list'+;  the element indicated by +'first'+
+must exist in the list.
+
++'last'+ gives the index in +'list'+ of the last element
+to be replaced;  it must be greater than or equal to +'first'+.
+
+See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'first'+ and +'last'+.
+
+The +'element'+ arguments specify zero or more new arguments to
+be added to the list in place of those that were deleted.
+
+Each +'element'+ argument will become a separate element of
+the list.
+
+If no +'element'+ arguments are specified, then the elements
+between +'first'+ and +'last'+ are simply deleted.
+
+lrepeat
+~~~~~~~~
++*lrepeat* 'number element1 ?element2 \...?'+
+
+Build a list by repeating elements +'number'+ times (which must be
+a positive integer).
+
+    jim> lrepeat 3 a b
+    a b a b a b
+
+lreverse
+~~~~~~~~
++*lreverse* 'list'+
+
+Returns the list in reverse order.
+
+    jim> lreverse {1 2 3}
+    3 2 1
+
+lsearch
+~~~~~~~
++*lsearch* '?options? list pattern'+
+
+This command searches the elements +'list'+ to see if one of them matches +'pattern'+. If so, the
+command returns the index of the first matching element (unless the options +-all+, +-inline+ or +-bool+ are
+specified.) If not, the command returns -1. The option arguments indicates how the elements of
+the list are to be matched against pattern and must have one of the values below:
+
+*Note* that this command is different from Tcl in that default match type is +-exact+ rather than +-glob+.
+
++*-exact*+::
+    +'pattern'+ is a literal string that is compared for exact equality against each list element.
+    This is the default.
+
++*-glob*+::
+    +'pattern'+ is a glob-style pattern which is matched against each list element using the same
+    rules as the string match command.
+
++*-regexp*+::
+    +'pattern'+ is treated as a regular expression and matched against each list element using
+    the rules described by `regexp`.
+
++*-command* 'cmdname'+::
+    +'cmdname'+ is a command which is used to match the pattern against each element of the
+    list. It is invoked as +'cmdname' ?*-nocase*? 'pattern listvalue'+ and should return 1
+    for a match, or 0 for no match.
+
++*-all*+::
+    Changes the result to be the list of all matching indices (or all matching values if
+    +-inline+ is specified as well). If indices are returned, the indices will be in numeric
+    order. If values are returned, the order of the values will be the order of those values
+    within the input list.
+
++*-inline*+::
+    The matching value is returned instead of its index (or an empty string if no value
+    matches). If +-all+ is also specified, then the result of the command is the list of all
+    values that matched. The +-inline+ and +-bool+ options are mutually exclusive.
+
++*-bool*+::
+    Changes the result to '1' if a match was found, or '0' otherwise. If +-all+ is also specified,
+    the result will be a list of '0' and '1' for each element of the list depending upon whether
+    the corresponding element matches. The +-inline+ and +-bool+ options are mutually exclusive.
+
++*-not*+::
+    This negates the sense of the match, returning the index (or value
+    if +-inline+ is specified) of the first non-matching value in the
+    list. If +-bool+ is also specified, the '0' will be returned if a
+    match is found, or '1' otherwise. If +-all+ is also specified,
+    non-matches will be returned rather than matches.
+
++*-nocase*+::
+    Causes comparisons to be handled in a case-insensitive manner.
+
+lsort
+~~~~~
++*lsort* ?*-index* 'listindex'? ?*-nocase!-integer|-real|-command* 'cmdname'? ?*-unique*? ?*-decreasing*|*-increasing*? 'list'+
+
+Sort the elements of +'list'+, returning a new list in sorted order.
+By default, ASCII (or UTF-8) sorting is used, with the result in increasing order.
+
+If +-nocase+ is specified, comparisons are case-insenstive.
+
+If +-integer+ is specified, numeric sorting is used.
+
+If +-real+ is specified, floating point number sorting is used.
+
+If +-command 'cmdname'+ is specified, +'cmdname'+ is treated as a command
+name. For each comparison, +'cmdname $value1 $value2+' is called which
+should compare the values and return an integer less than, equal
+to, or greater than zero if the +'$value1'+ is to be considered less
+than, equal to, or greater than +'$value2'+, respectively.
+
+If +-decreasing+ is specified, the resulting list is in the opposite
+order to what it would be otherwise. +-increasing+ is the default.
+
+If +-unique+ is specified, then only the last set of duplicate elements found in the list will be retained.
+Note that duplicates are determined relative to the comparison used in the sort. Thus if +-index 0+ is used,
++{1 a}+ and +{1 b}+ would be considered duplicates and only the second element, +{1 b}+, would be retained.
+
+If +-index 'listindex'+ is specified, each element of the list is treated as a list and
+the given index is extracted from the list for comparison. The list index may
+be any valid list index, such as +1+, +end+ or +end-2+.
+
+open
+~~~~
++*open* 'fileName ?access?'+
+
++*open* '|command-pipeline ?access?'+
+
+Opens a file and returns an identifier
+that may be used in future invocations
+of commands like `read`, `puts`, and `close`.
++'fileName'+ gives the name of the file to open.
+
+The +'access'+ argument indicates the way in which the file is to be accessed.
+It may have any of the following values:
+
++r+::
+    Open the file for reading only; the file must already exist.
+
++r++::
+    Open the file for both reading and writing; the file must
+    already exist.
+
++w+::
+    Open the file for writing only. Truncate it if it exists. If it doesn't
+    exist, create a new file.
+
++w++::
+    Open the file for reading and writing. Truncate it if it exists.
+    If it doesn't exist, create a new file.
+
++a+::
+    Open the file for writing only. The file must already exist, and the file
+    is positioned so that new data is appended to the file.
+
++a++::
+    Open the file for reading and writing. If the file doesn't
+    exist, create a new empty file. Set the initial access position
+    to the end of the file.
+
++'access'+ defaults to 'r'.
+
+If a file is opened for both reading and writing, then `seek`
+must be invoked between a read and a write, or vice versa.
+
+If the first character of +'fileName'+ is "|" then the remaining
+characters of +'fileName'+ are treated as a list of arguments that
+describe a command pipeline to invoke, in the same style as the
+arguments for exec. In this case, the channel identifier returned
+by open may be used to write to the command's input pipe or read
+from its output pipe, depending on the value of +'access'+. If write-only
+access is used (e.g. +'access'+ is 'w'), then standard output for the
+pipeline is directed to the current standard output unless overridden
+by the command. If read-only access is used (e.g. +'access'+ is r),
+standard input for the pipeline is taken from the current standard
+input unless overridden by the command.
+
+The `pid` command may be used to return the process ids of the commands
+forming the command pipeline.
+
+See also `socket`, `pid`, `exec`
+
+package
+~~~~~~~
++*package provide* 'name ?version?'+
+
+Indicates that the current script provides the package named +'name'+.
+If no version is specified, '1.0' is used.
+
+Any script which provides a package may include this statement
+as the first statement, although it is not required.
+
++*package require* 'name ?version?'*+
+
+Searches for the package with the given +'name'+ by examining each path
+in '$::auto_path' and trying to load '$path/$name.so' as a dynamic extension,
+or '$path/$name.tcl' as a script package.
+
+The first such file which is found is considered to provide the the package.
+(The version number is ignored).
+
+If '$name.so' exists, it is loaded with the `load` command,
+otherwise if '$name.tcl' exists it is loaded with the `source` command.
+
+If `load` or `source` fails, `package require` will fail immediately.
+No further attempt will be made to locate the file.
+
+pid
+~~~
++*pid*+
+
++*pid* 'fileId'+
+
+The first form returns the process identifier of the current process.
+
+The second form accepts a handle returned by `open` and returns a list
+of the process ids forming the pipeline in the same form as `exec ... &`.
+If 'fileId' represents a regular file handle rather than a command pipeline,
+the empty string is returned instead.
+
+See also `open`, `exec`
+
+proc
+~~~~
++*proc* 'name args ?statics? body'+
+
+The `proc` command creates a new Tcl command procedure, +'name'+.
+When the new command is invoked, the contents of +'body'+ will be executed.
+Tcl interpreter. +'args'+ specifies the formal arguments to the procedure.
+If specified, +'static'+, declares static variables which are bound to the
+procedure.
+
+See PROCEDURES for detailed information about Tcl procedures.
+
+The `proc` command returns +'name'+ (which is useful with `local`).
+
+When a procedure is invoked, the procedure's return value is the
+value specified in a `return` command.  If the procedure doesn't
+execute an explicit `return`, then its return value is the value
+of the last command executed in the procedure's body.
+
+If an error occurs while executing the procedure body, then the
+procedure-as-a-whole will return that same error.
+
+puts
+~~~~
++*puts* ?*-nonewline*? '?fileId? string'+
+
++'fileId' *puts* ?*-nonewline*? 'string'+
+
+Writes the characters given by +'string'+ to the file given
+by +'fileId'+. +'fileId'+ must have been the return
+value from a previous call to `open`, or it may be
++stdout+ or +stderr+ to refer to one of the standard I/O
+channels; it must refer to a file that was opened for
+writing.
+
+In the first form, if no +'fileId'+ is specified then it defaults to +stdout+.
+`puts` normally outputs a newline character after +'string'+,
+but this feature may be suppressed by specifying the +-nonewline+
+switch.
+
+Output to files is buffered internally by Tcl; the `flush`
+command may be used to force buffered characters to be output.
+
+pwd
+~~~
++*pwd*+
+
+Returns the path name of the current working directory.
+
+rand
+~~~~
++*rand* '?min? ?max?'+
+
+Returns a random integer between +'min'+ (defaults to 0) and +'max'+
+(defaults to the maximum integer).
+
+If only one argument is given, it is interpreted as +'max'+.
+
+range
+~~~~
++*range* '?start? end ?step?'+
+
+Returns a list of integers starting at +'start'+ (defaults to 0)
+and ranging up to but not including +'end'+ in steps of +'step'+ defaults to 1).
+
+    jim> range 5
+    0 1 2 3 4
+    jim> range 2 5
+    2 3 4
+    jim> range 2 10 4
+    2 6
+    jim> range 7 4 -2
+    7 5
+
+read
+~~~~
++*read* ?*-nonewline*? 'fileId'+
+
++'fileId' *read* ?*-nonewline*?+
+
++*read* 'fileId numBytes'+
+
++'fileId' *read* 'numBytes'+
+
+
+In the first form, all of the remaining bytes are read from the file
+given by +'fileId'+; they are returned as the result of the command.
+If the +-nonewline+ switch is specified then the last
+character of the file is discarded if it is a newline.
+
+In the second form, the extra argument specifies how many bytes to read;
+exactly this many bytes will be read and returned, unless there are fewer than
++'numBytes'+ bytes left in the file; in this case, all the remaining
+bytes are returned.
+
++'fileId'+ must be +stdin+ or the return value from a previous call
+to `open`; it must refer to a file that was opened for reading.
+
+regexp
+~~~~~~
++*regexp ?-nocase? ?-line? ?-indices? ?-start* 'offset'? *?-all? ?-inline? ?--?* 'exp string ?matchVar? ?subMatchVar subMatchVar \...?'+
+
+Determines whether the regular expression +'exp'+ matches part or
+all of +'string'+ and returns 1 if it does, 0 if it doesn't.
+
+See REGULAR EXPRESSIONS above for complete information on the
+syntax of +'exp'+ and how it is matched against +'string'+.
+
+If additional arguments are specified after +'string'+ then they
+are treated as the names of variables to use to return
+information about which part(s) of +'string'+ matched +'exp'+.
++'matchVar'+ will be set to the range of +'string'+ that
+matched all of +'exp'+. The first +'subMatchVar'+ will contain
+the characters in +'string'+ that matched the leftmost parenthesized
+subexpression within +'exp'+, the next +'subMatchVar'+ will
+contain the characters that matched the next parenthesized
+subexpression to the right in +'exp'+, and so on.
+
+Normally, +'matchVar'+ and the each +'subMatchVar'+ are set to hold the
+matching characters from `string`, however see +-indices+ and
++-inline+ below.
+
+If there are more values for +'subMatchVar'+ than parenthesized subexpressions
+within +'exp'+, or if a particular subexpression in +'exp'+ doesn't
+match the string (e.g. because it was in a portion of the expression
+that wasn't matched), then the corresponding +'subMatchVar'+ will be
+set to +"-1 -1"+ if +-indices+ has been specified or to an empty
+string otherwise.
+
+The following switches modify the behaviour of +'regexp'+
+
++*-nocase*+::
+    Causes upper-case and lower-case characters to be treated as
+    identical during the matching process.
+
++*-line*+::
+    Use newline-sensitive matching. By default, newline
+    is a completely ordinary character with no special meaning in
+    either REs or strings. With this flag, +[^+ bracket expressions
+    and +.+ never match newline, a +^+ anchor matches the null
+    string after any newline in the string in addition to its normal
+    function, and the +$+ anchor matches the null string before any
+    newline in the string in addition to its normal function.
+
++*-indices*+::
+    Changes what is stored in the subMatchVars. Instead of
+    storing the matching characters from string, each variable
+    will contain a list of two decimal strings giving the indices
+    in string of the first and last characters in the matching
+    range of characters.
+
++*-start* 'offset'+::
+    Specifies a character index offset into the string at which to start
+    matching the regular expression. If +-indices+ is
+    specified, the indices will be indexed starting from the
+    absolute beginning of the input string. +'offset'+ will be
+    constrained to the bounds of the input string.
+
++*-all*+::
+    Causes the regular expression to be matched as many times as possible
+    in the string, returning the total number of matches found. If this
+    is specified with match variables, they will contain information
+    for the last match only.
+
++*-inline*+::
+    Causes the command to return, as a list, the data that would otherwise
+    be placed in match variables. When using +-inline+, match variables
+    may not be specified. If used with +-all+, the list will be concatenated
+    at each iteration, such that a flat list is always returned. For
+    each match iteration, the command will append the overall match
+    data, plus one element for each subexpression in the regular
+    expression.
+
++*--*+::
+    Marks the end of switches. The argument following this one will be
+    treated as +'exp'+ even if it starts with a +-+.
+
+regsub
+~~~~~~
++*regsub ?-nocase? ?-all? ?-line? ?-start* 'offset'? ?*--*? 'exp string subSpec ?varName?'+
+
+This command matches the regular expression +'exp'+ against
++'string'+ using the rules described in REGULAR EXPRESSIONS
+above.
+
+If +'varName'+ is specified, the commands stores +'string'+ to +'varName'+
+with the substitutions detailed below, and returns the number of
+substitutions made (normally 1 unless +-all+ is specified).
+This is 0 if there were no matches.
+
+If +'varName'+ is not specified, the substituted string will be returned
+instead.
+
+When copying +'string'+, the portion of +'string'+ that
+matched +'exp'+ is replaced with +'subSpec'+.
+If +'subSpec'+ contains a +&+ or +{backslash}0+, then it is replaced
+in the substitution with the portion of +'string'+ that
+matched +'exp'+.
+
+If +'subSpec'+ contains a +{backslash}n+, where +'n'+ is a digit
+between 1 and 9, then it is replaced in the substitution with
+the portion of +'string'+ that matched the +'n'+\'-th
+parenthesized subexpression of +'exp'+.
+Additional backslashes may be used in +'subSpec'+ to prevent special
+interpretation of +&+ or +{backslash}0+ or +{backslash}n+ or
+backslash.
+
+The use of backslashes in +'subSpec'+ tends to interact badly
+with the Tcl parser's use of backslashes, so it's generally
+safest to enclose +'subSpec'+ in braces if it includes
+backslashes.
+
+The following switches modify the behaviour of +'regsub'+
+
++*-nocase*+::
+    Upper-case characters in +'string'+ are converted to lower-case
+    before matching against +'exp'+;  however, substitutions
+    specified by +'subSpec'+ use the original unconverted form
+    of +'string'+.
+
++*-all*+::
+    All ranges in +'string'+ that match +'exp'+ are found and substitution
+    is performed for each of these ranges, rather than only the
+    first. The +&+ and +{backslash}n+ sequences are handled for
+    each substitution using the information from the corresponding
+    match.
+
++*-line*+::
+    Use newline-sensitive matching. By default, newline
+    is a completely ordinary character with no special meaning in
+    either REs or strings.  With this flag, +[^+ bracket expressions
+    and +.+ never match newline, a +^+ anchor matches the null
+    string after any newline in the string in addition to its normal
+    function, and the +$+ anchor matches the null string before any
+    newline in the string in addition to its normal function.
+
++*-start* 'offset'+::
+    Specifies a character index offset into the string at which to
+    start matching the regular expression. +'offset'+ will be
+    constrained to the bounds of the input string.
+
++*--*+::
+    Marks the end of switches. The argument following this one will be
+    treated as +'exp'+ even if it starts with a +-+.
+
+ref
+~~~
++*ref* 'string tag ?finalizer?'+
+
+Create a new reference containing +'string'+ of type +'tag'+.
+If +'finalizer'+ is specified, it is a command which will be invoked
+when the a garbage collection cycle runs and this reference is
+no longer accessible.
+
+The finalizer is invoked as:
+
+  finalizer reference string
+
+See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.
+
+rename
+~~~~~~
++*rename* 'oldName newName'+
+
+Rename the command that used to be called +'oldName'+ so that it
+is now called +'newName'+.  If +'newName'+ is an empty string
+(e.g. {}) then +'oldName'+ is deleted.  The `rename` command
+returns an empty string as result.
+
+return
+~~~~~~
++*return* ?*-code* 'code'? ?*-errorinfo* 'stacktrace'? ?*-errorcode* 'errorcode'? ?*-level* 'n'? ?'value'?+
+
+Return immediately from the current procedure (or top-level command
+or `source` command), with +'value'+ as the return value.  If +'value'+
+is not specified, an empty string will be returned as result.
+
+If +-code+ is specified (as either a number or ok, error, break,
+continue, signal, return or exit), this code will be used instead
+of +JIM_OK+. This is generally useful when implementing flow of control
+commands.
+
+If +-level+ is specified and greater than 1, it has the effect of delaying
+the new return code from +-code+. This is useful when rethrowing an error
+from `catch`. See the implementation of try/catch in tclcompat.tcl for
+an example of how this is done.
+
+Note: The following options are only used when +-code+ is JIM_ERR.
+
+If +-errorinfo+ is specified (as returned from `info stacktrace`)
+it is used to initialize the stacktrace.
+
+If +-errorcode+ is specified, it is used to set the global variable $::errorCode.
+
+scan
+~~~~
++*scan* 'string format varName1 ?varName2 \...?'+
+
+This command parses fields from an input string in the same fashion
+as the C 'sscanf' procedure.  +'string'+ gives the input to be parsed
+and +'format'+ indicates how to parse it, using '%' fields as in
+'sscanf'.  All of the 'sscanf' options are valid; see the 'sscanf'
+man page for details.  Each +'varName'+ gives the name of a variable;
+when a field is scanned from +'string'+, the result is converted back
+into a string and assigned to the corresponding +'varName'+.  The
+only unusual conversion is for '%c'.  For '%c' conversions a single
+character value is converted to a decimal string, which is then
+assigned to the corresponding +'varName'+; no field width may be
+specified for this conversion.
+
+seek
+~~~~
++*seek* 'fileId offset ?origin?'+
+
++'fileId' *seek* 'offset ?origin?'+
+
+Change the current access position for +'fileId'+.
+The +'offset'+ and +'origin'+ arguments specify the position at
+which the next read or write will occur for +'fileId'+.
++'offset'+ must be a number (which may be negative) and +'origin'+
+must be one of the following:
+
++*start*+::
+    The new access position will be +'offset'+ bytes from the start
+    of the file.
+
++*current*+::
+    The new access position will be +'offset'+ bytes from the current
+    access position; a negative +'offset'+ moves the access position
+    backwards in the file.
+
++*end*+::
+    The new access position will be +'offset'+ bytes from the end of
+    the file.  A negative +'offset'+ places the access position before
+    the end-of-file, and a positive +'offset'+ places the access position
+    after the end-of-file.
+
+The +'origin'+ argument defaults to +start+.
+
++'fileId'+ must have been the return value from a previous call to
+`open`, or it may be +stdin+, +stdout+, or +stderr+ to refer to one
+of the standard I/O channels.
+
+This command returns an empty string.
+
+set
+~~~
++*set* 'varName ?value?'+
+
+Returns the value of variable +'varName'+.
+
+If +'value'+ is specified, then set the value of +'varName'+ to +'value'+,
+creating a new variable if one doesn't already exist, and return
+its value.
+
+If +'varName'+ contains an open parenthesis and ends with a
+close parenthesis, then it refers to an array element:  the characters
+before the open parenthesis are the name of the array, and the characters
+between the parentheses are the index within the array.
+Otherwise +'varName'+ refers to a scalar variable.
+
+If no procedure is active, then +'varName'+ refers to a global
+variable.
+
+If a procedure is active, then +'varName'+ refers to a parameter
+or local variable of the procedure, unless the +'global'+ command
+has been invoked to declare +'varName'+ to be global.
+
+The +::+ prefix may also be used to explicitly reference a variable
+in the global scope.
+
+setref
+~~~~~~
++*setref* 'reference string'+
+
+Store a new string in +'reference'+, replacing the existing string.
+The reference must be a valid reference create with the `ref`
+command.
+
+See GARBAGE COLLECTION, REFERENCES, LAMBDA for more detail.
+
+signal
+~~~~~~
+Command for signal handling.
+
+See `kill` for the different forms which may be used to specify signals.
+
+Commands which return a list of signal names do so using the canonical form:
+"+SIGINT SIGTERM+".
+
++*signal handle* ?'signals \...'?+::
+    If no signals are given, returns a list of all signals which are currently
+    being handled.
+    If signals are specified, these are added to the list of signals currently
+    being handled.
+
++*signal ignore* ?'signals \...'?+::
+    If no signals are given, returns a lists all signals which are currently
+    being ignored.
+    If signals are specified, these are added to the list of signals
+    currently being ignored. These signals are still delivered, but
+    are not considered by `catch -signal` or `try -signal`. Use
+    `signal check` to determine which signals have occurred but
+    been ignored.
+
++*signal default* ?'signals \...'?+::
+    If no signals are given, returns a lists all signals which are currently have
+    the default behaviour.
+    If signals are specified, these are added to the list of signals which have
+    the default behaviour.
+
++*signal check ?-clear?* ?'signals \...'?+::
+    Returns a list of signals which have been delivered to the process
+    but are 'ignored'. If signals are specified, only that set of signals will
+    be checked, otherwise all signals will be checked.
+    If +-clear+ is specified, any signals returned are removed and will not be
+    returned by subsequent calls to `signal check` unless delivered again.
+
++*signal throw* ?'signal'?+::
+    Raises the given signal, which defaults to +SIGINT+ if not specified.
+    The behaviour is identical to:
+
+        kill signal [pid]
+
+Note that `signal handle` and `signal ignore` represent two forms of signal
+handling. `signal handle` is used in conjunction with `catch -signal` or `try -signal`
+to immediately abort execution when the signal is delivered. Alternatively, `signal ignore`
+is used in conjunction with `signal check` to handle signal synchronously. Consider the
+two examples below.
+
+Prevent a processing from taking too long
+
+    signal handle SIGALRM
+    alarm 20
+    try -signal {
+        .. possibly long running process ..
+        alarm 0
+    } on signal {sig} {
+        puts stderr "Process took too long"
+    }
+
+Handle SIGHUP to reconfigure:
+
+    signal ignore SIGHUP
+    while {1} {
+        ... handle configuration/reconfiguration ...
+        while {[signal check -clear SIGHUP] eq ""} {
+            ... do processing ..
+        }
+        # Received SIGHUP, so reconfigure
+    }
+
+sleep
+~~~~~
++*sleep* 'seconds'+
+
+Pauses for the given number of seconds, which may be a floating
+point value less than one to sleep for less than a second, or an
+integer to sleep for one or more seconds.
+
+source
+~~~~~~
++*source* 'fileName'+
+
+Read file +'fileName'+ and pass the contents to the Tcl interpreter
+as a sequence of commands to execute in the normal fashion.  The return
+value of `source` is the return value of the last command executed
+from the file.  If an error occurs in executing the contents of the
+file, then the `source` command will return that error.
+
+If a `return` command is invoked from within the file, the remainder of
+the file will be skipped and the `source` command will return
+normally with the result from the `return` command.
+
+split
+~~~~~
++*split* 'string ?splitChars?'+
+
+Returns a list created by splitting +'string'+ at each character
+that is in the +'splitChars'+ argument.
+
+Each element of the result list will consist of the
+characters from +'string'+ between instances of the
+characters in +'splitChars'+.
+
+Empty list elements will be generated if +'string'+ contains
+adjacent characters in +'splitChars'+, or if the first or last
+character of +'string'+ is in +'splitChars'+.
+
+If +'splitChars'+ is an empty string then each character of
++'string'+ becomes a separate element of the result list.
+
++'splitChars'+ defaults to the standard white-space characters.
+For example,
+
+    split "comp.unix.misc" .
+
+returns +'"comp unix misc"'+ and
+
+    split "Hello world" {}
+
+returns +'"H e l l o { } w o r l d"'+.
+
+stackdump
+~~~~~~~~~
+
++*stackdump* 'stacktrace'+
+
+Creates a human readable representation of a stack trace.
+
+stacktrace
+~~~~~~~~~~
+
++*stacktrace*+
+
+Returns a live stack trace as a list of +proc file line proc file line \...+.
+Iteratively uses `info frame` to create the stack trace. This stack trace is in the
+same form as produced by `catch` and `info stacktrace`
+
+See also `stackdump`.
+
+string
+~~~~~~
+
++*string* 'option arg ?arg \...?'+
+
+Perform one of several string operations, depending on +'option'+.
+The legal options (which may be abbreviated) are:
+
++*string bytelength* 'string'+::
+    Returns the length of the string in bytes. This will return
+    the same value as `string length` if UTF-8 support is not enabled,
+    or if the string is composed entirely of ASCII characters.
+    See UTF-8 AND UNICODE.
+
++*string byterange* 'string first last'+::
+    Like `string range` except works on bytes rather than characters.
+    These commands are identical if UTF-8 support is not enabled.
+
++*string compare ?-nocase?* ?*-length* 'len? string1 string2'+::
+    Perform a character-by-character comparison of strings +'string1'+ and
+    +'string2'+ in the same way as the C 'strcmp' procedure.  Return
+    -1, 0, or 1, depending on whether +'string1'+ is lexicographically
+    less than, equal to, or greater than +'string2'+. If +-length+
+    is specified, then only the first +'len'+ characters are used
+    in the comparison.  If +'len'+ is negative, it is ignored.
+    Performs a case-insensitive comparison if +-nocase+ is specified.
+
++*string equal ?-nocase?* '?*-length* len?' 'string1 string2'+::
+    Returns 1 if the strings are equal, or 0 otherwise. If +-length+
+    is specified, then only the first +'len'+ characters are used
+    in the comparison.  If +'len'+ is negative, it is ignored.
+    Performs a case-insensitive comparison if +-nocase+ is specified.
+
++*string first* 'string1 string2 ?firstIndex?'+::
+    Search +'string2'+ for a sequence of characters that exactly match
+    the characters in +'string1'+.  If found, return the index of the
+    first character in the first such match within +'string2'+.  If not
+    found, return -1. If +'firstIndex'+ is specified, matching will start
+    from +'firstIndex'+ of +'string1'+.
+ ::
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'firstIndex'+.
+
++*string index* 'string charIndex'+::
+    Returns the +'charIndex'+'th character of the +'string'+
+    argument.  A +'charIndex'+ of 0 corresponds to the first
+    character of the string.
+    If +'charIndex'+ is less than 0 or greater than
+    or equal to the length of the string then an empty string is
+    returned.
+ ::
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'charIndex'+.
+
++*string is* 'class' ?*-strict*? 'string'+::
+    Returns 1 if +'string'+ is a valid member of the specified character
+    class, otherwise returns 0. If +-strict+ is specified, then an
+    empty string returns 0, otherwise an empty string will return 1
+    on any class. The following character classes are recognized
+    (the class name can be abbreviated):
+  ::
+  +alnum+;;  Any alphabet or digit character.
+  +alpha+;;  Any alphabet character.
+  +ascii+;;  Any character with a value less than 128 (those that are in the 7-bit ascii range).
+  +control+;; Any control character.
+  +digit+;;  Any digit character.
+  +double+;; Any of the valid forms for a double in Tcl, with optional surrounding whitespace.
+             In case of under/overflow in the value, 0 is returned.
+  +graph+;;  Any printing character, except space.
+  +integer+;; Any of the valid string formats for an integer value in Tcl, with optional surrounding whitespace.
+  +lower+;;  Any lower case alphabet character.
+  +print+;;  Any printing character, including space.
+  +punct+;;  Any punctuation character.
+  +space+;;  Any space character.
+  +upper+;;  Any upper case alphabet character.
+  +xdigit+;; Any hexadecimal digit character ([0-9A-Fa-f]).
+ ::
+    Note that string classification does +'not'+ respect UTF-8. See UTF-8 AND UNICODE
+
++*string last* 'string1 string2 ?lastIndex?'+::
+    Search +'string2'+ for a sequence of characters that exactly match
+    the characters in +'string1'+.  If found, return the index of the
+    first character in the last such match within +'string2'+.  If there
+    is no match, then return -1. If +'lastIndex'+ is specified, only characters
+    up to +'lastIndex'+ of +'string2'+ will be considered in the match.
+ ::
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'lastIndex'+.
+
++*string length* 'string'+::
+    Returns a decimal string giving the number of characters in +'string'+.
+    If UTF-8 support is enabled, this may be different than the number of bytes.
+    See UTF-8 AND UNICODE
+
++*string map ?-nocase?* 'mapping string'+::
+    Replaces substrings in +'string'+ based on the key-value pairs in
+    +'mapping'+, which is a list of +key value key value \...+ as in the form
+    returned by `array get`. Each instance of a key in the string will be
+    replaced with its corresponding value.  If +-nocase+ is specified, then
+    matching is done without regard to case differences. Both key and value may
+    be multiple characters.  Replacement is done in an ordered manner, so the
+    key appearing first in the list will be checked first, and so on. +'string'+ is
+    only iterated over once, so earlier key replacements will have no affect for
+    later key matches. For example,
+
+      string map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc
+
+ ::
+    will return the string +01321221+.
+ ::
+    Note that if an earlier key is a prefix of a later one, it will completely mask the later
+    one.  So if the previous example is reordered like this,
+
+      string map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc
+
+ ::
+    it will return the string +02c322c222c+.
+
++*string match ?-nocase?* 'pattern string'+::
+    See if +'pattern'+ matches +'string'+; return 1 if it does, 0
+    if it doesn't.  Matching is done in a fashion similar to that
+    used by the C-shell.  For the two strings to match, their contents
+    must be identical except that the following special sequences
+    may appear in +'pattern'+:
+
+    +*+;;
+        Matches any sequence of characters in +'string'+,
+        including a null string.
+
+    +?+;;
+        Matches any single character in +'string'+.
+
+    +['chars']+;;
+        Matches any character in the set given by +'chars'+.
+        If a sequence of the form +'x-y'+ appears in +'chars'+,
+        then any character between +'x'+ and +'y'+, inclusive,
+        will match.
+
+    +{backslash}x+;;
+        Matches the single character +'x'+.  This provides a way of
+        avoiding the special interpretation of the characters +{backslash}*?[]+
+        in +'pattern'+.
+ ::
+    Performs a case-insensitive comparison if +-nocase+ is specified.
+
++*string range* 'string first last'+::
+    Returns a range of consecutive characters from +'string'+, starting
+    with the character whose index is +'first'+ and ending with the
+    character whose index is +'last'+.  An index of 0 refers to the
+    first character of the string.
+ ::
+    See STRING AND LIST INDEX SPECIFICATIONS for all allowed forms for +'first'+ and +'last'+.
+ ::
+    If +'first'+ is less than zero then it is treated as if it were zero, and
+    if +'last'+ is greater than or equal to the length of the string then
+    it is treated as if it were +end+.  If +'first'+ is greater than
+    +'last'+ then an empty string is returned.
+
++*string repeat* 'string count'+::
+    Returns a new string consisting of +'string'+ repeated +'count'+ times.
+
++*string replace* 'string first last ?newstring?'+::
+    Removes a range of consecutive characters from +'string'+, starting
+    with the character whose index is +'first'+ and ending with the
+    character whose index is +'last'+.  If +'newstring'+ is specified,
+    then it is placed in the removed character range. If +'first'+ is
+    less than zero then it is treated as if it were zero, and if +'last'+
+    is greater than or equal to the length of the string then it is
+    treated as if it were +end+. If +'first'+ is greater than +'last'+
+    or the length of the initial string, or +'last'+ is less than 0,
+    then the initial string is returned untouched.
+
++*string reverse* 'string'+::
+    Returns a string that is the same length as +'string'+ but
+    with its characters in the reverse order.
+
++*string tolower* 'string'+::
+    Returns a value equal to +'string'+ except that all upper case
+    letters have been converted to lower case.
+
++*string totitle* 'string'+::
+    Returns a value equal to +'string'+ except that the first character
+    is converted to title case (or upper case if there is no UTF-8 titlecase variant)
+    and all remaining characters have been converted to lower case.
+
++*string toupper* 'string'+::
+    Returns a value equal to +'string'+ except that all lower case
+    letters have been converted to upper case.
+
++*string trim* 'string ?chars?'+::
+    Returns a value equal to +'string'+ except that any leading
+    or trailing characters from the set given by +'chars'+ are
+    removed.
+    If +'chars'+ is not specified then white space is removed
+    (spaces, tabs, newlines, and carriage returns).
+
++*string trimleft* 'string ?chars?'+::
+    Returns a value equal to +'string'+ except that any
+    leading characters from the set given by +'chars'+ are
+    removed.
+    If +'chars'+ is not specified then white space is removed
+    (spaces, tabs, newlines, and carriage returns).
+
++*string trimright* 'string ?chars?'+::
+    Returns a value equal to +'string'+ except that any
+    trailing characters from the set given by +'chars'+ are
+    removed.
+    If +'chars'+ is not specified then white space is removed
+    (spaces, tabs, newlines, and carriage returns).
+    Null characters are always removed.
+
+subst
+~~~~~
++*subst ?-nobackslashes? ?-nocommands? ?-novariables?* 'string'+
+
+This command performs variable substitutions, command substitutions,
+and backslash substitutions on its string argument and returns the
+fully-substituted result. The substitutions are performed in exactly
+the same way as for Tcl commands. As a result, the string argument
+is actually substituted twice, once by the Tcl parser in the usual
+fashion for Tcl commands, and again by the subst command.
+
+If any of the +-nobackslashes+, +-nocommands+, or +-novariables+ are
+specified, then the corresponding substitutions are not performed.
+For example, if +-nocommands+ is specified, no command substitution
+is performed: open and close brackets are treated as ordinary
+characters with no special interpretation.
+
+*Note*: when it performs its substitutions, subst does not give any
+special treatment to double quotes or curly braces. For example,
+the following script returns +xyz \{44\}+, not +xyz \{$a\}+.
+
+    set a 44
+    subst {xyz {$a}}
+
+
+switch
+~~~~~~
++*switch* '?options? string pattern body ?pattern body \...?'+
+
++*switch* '?options? string {pattern body ?pattern body \...?}'+
+
+The `switch` command matches its string argument against each of
+the pattern arguments in order. As soon as it finds a pattern that
+matches string it evaluates the following body and returns the
+result of that evaluation. If the last pattern argument is default
+then it matches anything. If no pattern argument matches string and
+no default is given, then the `switch` command returns an empty string.
+If the initial arguments to switch start with - then they are treated
+as options. The following options are currently supported:
+
+    +-exact+::
+        Use exact matching when comparing string to a
+        pattern. This is the default.
+
+    +-glob+::
+        When matching string to the patterns, use glob-style
+        matching (i.e. the same as implemented by the string
+        match command).
+
+    +-regexp+::
+        When matching string to the patterns, use regular
+        expression matching (i.e. the same as implemented
+        by the regexp command).
+
+    +-command 'commandname'+::
+        When matching string to the patterns, use the given command, which
+        must be a single word. The command is invoked as
+        'commandname pattern string', or 'commandname -nocase pattern string'
+        and must return 1 if matched, or 0 if not.
+
+    +--+::
+        Marks the end of options. The argument following
+        this one will be treated as string even if it starts
+        with a +-+.
+
+Two syntaxes are provided for the pattern and body arguments. The
+first uses a separate argument for each of the patterns and commands;
+this form is convenient if substitutions are desired on some of the
+patterns or commands. The second form places all of the patterns
+and commands together into a single argument; the argument must
+have proper list structure, with the elements of the list being the
+patterns and commands. The second form makes it easy to construct
+multi-line `switch` commands, since the braces around the whole list
+make it unnecessary to include a backslash at the end of each line.
+Since the pattern arguments are in braces in the second form, no
+command or variable substitutions are performed on them; this makes
+the behaviour of the second form different than the first form in
+some cases.
+
+If a body is specified as +-+ it means that the body for the next
+pattern should also be used as the body for this pattern (if the
+next pattern also has a body of +-+ then the body after that is
+used, and so on). This feature makes it possible to share a single
+body among several patterns.
+
+Below are some examples of `switch` commands:
+
+    switch abc a - b {format 1} abc {format 2} default {format 3}
+
+will return 2,
+
+    switch -regexp aaab {
+           ^a.*b$ -
+           b {format 1}
+           a* {format 2}
+           default {format 3}
+    }
+
+will return 1, and
+
+    switch xyz {
+           a -
+           b {format 1}
+           a* {format 2}
+           default {format 3}
+    }
+
+will return 3.
+
+tailcall
+~~~~~~~~
++*tailcall* 'cmd ?arg\...?'+
+
+The `tailcall` command provides an optimised way of invoking a command whilst replacing
+the current call frame. This is similar to 'exec' in Bourne Shell.
+
+The following are identical except the first immediately replaces the current call frame.
+
+  tailcall a b c
+
+  return [uplevel 1 [list a b c]]
+
+`tailcall` is useful as a dispatch mechanism:
+
+  proc a {cmd args} {
+    tailcall sub_$cmd {*}$args
+  }
+  proc sub_cmd1 ...
+  proc sub_cmd2 ...
+
+tell
+~~~~
++*tell* 'fileId'+
+
++'fileId' *tell*+
+
+Returns a decimal string giving the current access position in
++'fileId'+.
+
++'fileId'+ must have been the return value from a previous call to
+`open`, or it may be +stdin+, +stdout+, or +stderr+ to refer to one
+of the standard I/O channels.
+
+throw
+~~~~~
++*throw* 'code ?msg?'+
+
+This command throws an exception (return) code along with an optional message.
+This command is mostly for convenient usage with `try`.
+
+The command +throw break+ is equivalent to +break+.
+The command +throw 20 message+ can be caught with an +on 20 \...+ clause to `try`.
+
+time
+~~~~
++*time* 'command ?count?'+
+
+This command will call the Tcl interpreter +'count'+
+times to execute +'command'+ (or once if +'count'+ isn't
+specified).  It will then return a string of the form
+
+    503 microseconds per iteration
+
+which indicates the average amount of time required per iteration,
+in microseconds.
+
+Time is measured in elapsed time, not CPU time.
+
+try
+~~~
++*try* '?catchopts? tryscript' ?*on* 'returncodes {?resultvar? ?optsvar?} handlerscript \...'? ?*finally* 'finalscript'?+
+
+The `try` command is provided as a convenience for exception handling.
+
+This interpeter first evaluates +'tryscript'+ under the effect of the catch
+options +'catchopts'+ (e.g. +-signal -noexit --+, see `catch`).
+
+It then evaluates the script for the first matching 'on' handler
+(there many be zero or more) based on the return code from the `try`
+section. For example a normal +JIM_ERR+ error will be matched by
+an 'on error' handler.
+
+Finally, any +'finalscript'+ is evaluated.
+
+The result of this command is the result of +'tryscript'+, except in the
+case where an exception occurs in a matching 'on' handler script or the 'finally' script,
+in which case the result is this new exception.
+
+The specified +'returncodes'+ is a list of return codes either as names ('ok', 'error', 'break', etc.)
+or as integers.
+
+If +'resultvar'+ and +'optsvar'+ are specified, they are set as for `catch` before evaluating
+the matching handler.
+
+For example:
+
+    set f [open input]
+    try -signal {
+        process $f
+    } on {continue break} {} {
+        error "Unexpected break/continue"
+    } on error {msg opts} {
+        puts "Dealing with error"
+        return {*}$opts $msg
+    } on signal sig {
+        puts "Got signal: $sig"
+    } finally {
+        $f close
+    }
+
+If break, continue or error are raised, they are dealt with by the matching
+handler.
+
+In any case, the file will be closed via the 'finally' clause.
+
+See also `throw`, `catch`, `return`, `error`.
+
+unknown
+~~~~~~~
++*unknown* 'cmdName ?arg arg ...?'+
+
+This command doesn't actually exist as part of Tcl, but Tcl will
+invoke it if it does exist.
+
+If the Tcl interpreter encounters a command name for which there
+is not a defined command, then Tcl checks for the existence of
+a command named `unknown`.
+
+If there is no such command, then the interpreter returns an
+error.
+
+If the `unknown` command exists, then it is invoked with
+arguments consisting of the fully-substituted name and arguments
+for the original non-existent command.
+
+The `unknown` command typically does things like searching
+through library directories for a command procedure with the name
++'cmdName'+, or expanding abbreviated command names to full-length,
+or automatically executing unknown commands as UNIX sub-processes.
+
+In some cases (such as expanding abbreviations) `unknown` will
+change the original command slightly and then (re-)execute it.
+The result of the `unknown` command is used as the result for
+the original non-existent command.
+
+unset
+~~~~~
++*unset ?-nocomplain? ?--?* '?name name ...?'+
+
+Remove variables.
+Each +'name'+ is a variable name, specified in any of the
+ways acceptable to the `set` command.
+
+If a +'name'+ refers to an element of an array, then that
+element is removed without affecting the rest of the array.
+
+If a +'name'+ consists of an array name with no parenthesized
+index, then the entire array is deleted.
+
+The `unset` command returns an empty string as result.
+
+An error occurs if any of the variables doesn't exist, unless '-nocomplain'
+is specified. The '--' argument may be specified to stop option processing
+in case the variable name may be '-nocomplain'.
+
+upcall
+~~~~~~~
++*upcall* 'command ?args ...?'+
+
+May be used from within a proc defined as `local` `proc` in order to call
+the previous, hidden version of the same command.
+
+If there is no previous definition of the command, an error is returned.
+
+uplevel
+~~~~~~~
++*uplevel* '?level? command ?command ...?'+
+
+All of the +'command'+ arguments are concatenated as if they had
+been passed to `concat`; the result is then evaluated in the
+variable context indicated by +'level'+.  `uplevel` returns
+the result of that evaluation.  If +'level'+ is an integer, then
+it gives a distance (up the procedure calling stack) to move before
+executing the command.  If +'level'+ consists of +\#+ followed by
+a number then the number gives an absolute level number.  If +'level'+
+is omitted then it defaults to +1+.  +'level'+ cannot be
+defaulted if the first +'command'+ argument starts with a digit or +#+.
+
+For example, suppose that procedure 'a' was invoked
+from top-level, and that it called 'b', and that 'b' called 'c'.
+Suppose that 'c' invokes the `uplevel` command.  If +'level'+
+is +1+ or +#2+  or omitted, then the command will be executed
+in the variable context of 'b'.  If +'level'+ is +2+ or +#1+
+then the command will be executed in the variable context of 'a'.
+
+If +'level'+ is '3' or +#0+ then the command will be executed
+at top-level (only global variables will be visible).
+The `uplevel` command causes the invoking procedure to disappear
+from the procedure calling stack while the command is being executed.
+In the above example, suppose 'c' invokes the command
+
+    uplevel 1 {set x 43; d}
+
+where 'd' is another Tcl procedure.  The `set` command will
+modify the variable 'x' in 'b's context, and 'd' will execute
+at level 3, as if called from 'b'.  If it in turn executes
+the command
+
+    uplevel {set x 42}
+
+then the `set` command will modify the same variable 'x' in 'b's
+context:  the procedure 'c' does not appear to be on the call stack
+when 'd' is executing.  The command `info level` may
+be used to obtain the level of the current procedure.
+
+`uplevel` makes it possible to implement new control
+constructs as Tcl procedures (for example, `uplevel` could
+be used to implement the `while` construct as a Tcl procedure).
+
+upvar
+~~~~~
++*upvar* '?level? otherVar myVar ?otherVar myVar ...?'+
+
+This command arranges for one or more local variables in the current
+procedure to refer to variables in an enclosing procedure call or
+to global variables.
+
++'level'+ may have any of the forms permitted for the `uplevel`
+command, and may be omitted if the first letter of the first +'otherVar'+
+isn't +#+ or a digit (it defaults to '1').
+
+For each +'otherVar'+ argument, `upvar` makes the variable
+by that name in the procedure frame given by +'level'+ (or at
+global level, if +'level'+ is +#0+) accessible
+in the current procedure by the name given in the corresponding
++'myVar'+ argument.
+
+The variable named by +'otherVar'+ need not exist at the time of the
+call;  it will be created the first time +'myVar'+ is referenced, just like
+an ordinary variable.
+
+`upvar` may only be invoked from within procedures.
+
+`upvar` returns an empty string.
+
+The `upvar` command simplifies the implementation of call-by-name
+procedure calling and also makes it easier to build new control constructs
+as Tcl procedures.
+For example, consider the following procedure:
+
+    proc add2 name {
+        upvar $name x
+        set x [expr $x+2]
+    }
+
+'add2' is invoked with an argument giving the name of a variable,
+and it adds two to the value of that variable.
+Although 'add2' could have been implemented using `uplevel`
+instead of `upvar`, `upvar` makes it simpler for 'add2'
+to access the variable in the caller's procedure frame.
+
+while
+~~~~~
++*while* 'test body'+
+
+The +'while'+ command evaluates +'test'+ as an expression
+(in the same way that `expr` evaluates its argument).
+The value of the expression must be numeric; if it is non-zero
+then +'body'+ is executed by passing it to the Tcl interpreter.
+
+Once +'body'+ has been executed then +'test'+ is evaluated
+again, and the process repeats until eventually +'test'+
+evaluates to a zero numeric value.  `continue`
+commands may be executed inside +'body'+ to terminate the current
+iteration of the loop, and `break`
+commands may be executed inside +'body'+ to cause immediate
+termination of the `while` command.
+
+The `while` command always returns an empty string.
+
+OPTIONAL-EXTENSIONS
+-------------------
+
+The following extensions may or may not be available depending upon
+what options were selected when Jim Tcl was built.
+
+[[cmd_1]]
+posix: os.fork, os.wait, os.gethostname, os.getids, os.uptime
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++*os.fork*+::
+    Invokes 'fork(2)' and returns the result.
+
++*os.wait -nohang* 'pid'+::
+    Invokes waitpid(2), with WNOHANG if +-nohang+ is specified.
+    Returns a list of 3 elements.
+
+   {0 none 0} if -nohang is specified, and the process is still alive.
+
+   {-1 error <error-description>} if the process does not exist or has already been waited for.
+
+   {<pid> exit <exit-status>} if the process exited normally.
+
+   {<pid> signal <signal-number>} if the process terminated on a signal.
+
+   {<pid> other 0} otherwise (core dump, stopped, continued, etc.)
+
++*os.gethostname*+::
+    Invokes 'gethostname(3)' and returns the result.
+
++*os.getids*+::
+    Returns the various user/group ids for the current process.
+
+    jim> os.getids
+    uid 1000 euid 1000 gid 100 egid 100
+
++*os.uptime*+::
+    Returns the number of seconds since system boot. See description of 'uptime' in 'sysinfo(2)'.
+
+ANSI I/O (aio) and EVENTLOOP API
+--------------------------------
+Jim provides an alternative object-based API for I/O.
+
+See `open` and `socket` for commands which return an I/O handle.
+
+aio
+~~~
++$handle *accept*+::
+    Server socket only: Accept a connection and return stream
+
++$handle *buffering none|line|full*+::
+    Sets the buffering mode of the stream.
+
++$handle *close* ?r(ead)|w(rite)?+::
+    Closes the stream. 
+       The  two-argument form is a "half-close" on a socket. See the +shutdown(2)+ man page.
+
++$handle *copyto* 'tofd ?size?'+::
+    Copy bytes to the file descriptor +'tofd'+. If +'size'+ is specified, at most
+    that many bytes will be copied. Otherwise copying continues until the end
+    of the input file. Returns the number of bytes actually copied.
+
++$handle *eof*+::
+    Returns 1 if stream is at eof
+
++$handle *filename*+::
+    Returns the original filename associated with the handle.
+    Handles returned by `socket` give the socket type instead of a filename.
+
++$handle *flush*+::
+    Flush the stream
+
++$handle *gets* '?var?'+::
+    Read one line and return it or store it in the var
+
++$handle *isatty*+::
+    Returns 1 if the stream is a tty device.
+
++$handle *ndelay ?0|1?*+::
+    Set O_NDELAY (if arg). Returns current/new setting.
+    Note that in general ANSI I/O interacts badly with non-blocking I/O.
+    Use with care.
+
++$handle *puts ?-nonewline?* 'str'+::
+    Write the string, with newline unless -nonewline
+
++$handle *read ?-nonewline?* '?len?'+::
+    Read and return bytes from the stream. To eof if no len.
+
++$handle *recvfrom* 'maxlen ?addrvar?'+::
+    Receives a message from the handle via recvfrom(2) and returns it.
+    At most +'maxlen'+ bytes are read.
+    If +'addrvar'+ is specified, the sending address of the message is stored in
+    the named variable in the form 'addr:port'. See `socket` for details.
+
++$handle *seek* 'offset' *?start|current|end?*+::
+    Seeks in the stream (default 'current')
+
++$handle *sendto* 'str ?addr:?port'+::
+    Sends the string, +'str'+, to the given address via the socket using sendto(2).
+    This is intended for udp/dgram sockets and may give an error or behave in unintended
+    ways for other handle types.
+    Returns the number of bytes written.
+
++$handle *tell*+::
+    Returns the current seek position
+
+fconfigure
+~~~~~~~~~~
++*fconfigure* 'handle' *?-blocking 0|1? ?-buffering noneline|full? ?-translation* 'mode'?+::
+    For compatibility with Tcl, a limited form of the `fconfigure`
+    command is supported.
+    * `fconfigure ... -blocking` maps to `aio ndelay`
+    * `fconfigure ... -buffering` maps to `aio buffering`
+    * `fconfigure ... -translation` is accepted but ignored
+
+[[cmd_2]]
+eventloop: after, vwait, update
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following commands allow a script to be invoked when the given condition occurs.
+If no script is given, returns the current script. If the given script is the empty, the
+handler is removed.
+
++$handle *readable* '?readable-script?'+::
+    Sets or returns the script for when the socket is readable.
+
++$handle *writable* '?writable-script?'+::
+    Sets or returns the script for when the socket is writable.
+
++$handle *onexception* '?exception-script?'+::
+    Sets or returns the script for when when oob data received.
+
+For compatibility with 'Tcl', these may be prefixed with `fileevent`.  e.g.
+
+ ::
+    +fileevent $handle *readable* '\...'+
+
+Time-based execution is also available via the eventloop API.
+
++*after* 'ms'+::
+    Sleeps for the given number of milliseconds. No events are
+    processed during this time.
+
++*after* 'ms'|*idle* script ?script \...?'+::
+    The scripts are concatenated and executed after the given
+    number of milliseconds have elapsed.  If 'idle' is specified,
+    the script will run the next time the event loop is processed
+    with `vwait` or `update`. The script is only run once and
+    then removed.  Returns an event id.
+
++*after cancel* 'id|command'+::
+    Cancels an `after` event with the given event id or matching
+    command (script).  Returns the number of milliseconds
+    remaining until the event would have fired.  Returns the
+    empty string if no matching event is found.
+
++*after info* '?id?'+::
+    If +'id'+ is not given, returns a list of current `after`
+    events.  If +'id'+ is given, returns a list containing the
+    associated script and either 'timer' or 'idle' to indicated
+    the type of the event. An error occurs if +'id'+ does not
+    match an event.
+
++*vwait* 'variable'+::
+    A call to `vwait` is enters the eventloop. `vwait` processes
+    events until the named (global) variable changes or all
+    event handlers are removed. The variable need not exist
+    beforehand.  If there are no event handlers defined, `vwait`
+    returns immediately.
+
++*update ?idletasks?*+::
+    A call to `update` enters the eventloop to process expired events, but
+    no new events. If 'idletasks' is specified, only expired time events are handled,
+    not file events.
+    Returns once handlers have been run for all expired events.
+
+Scripts are executed at the global scope. If an error occurs during a handler script,
+an attempt is made to call (the user-defined command) `bgerror` with the details of the error.
+If the `bgerror` command does not exist, the error message details are printed to stderr instead.
+
+If a file event handler script generates an error, the handler is automatically removed
+to prevent infinite errors. (A time event handler is always removed after execution).
+
++*bgerror* 'msg'+::
+    Called when an event handler script generates an error. Note that the normal command resolution
+       rules are used for bgerror. First the name is resolved in the current namespace, then in the
+       global scope.
+
+socket
+~~~~~~
+Various socket types may be created.
+
++*socket unix* 'path'+::
+    A unix domain socket client.
+
++*socket unix.server* 'path'+::
+    A unix domain socket server.
+
++*socket ?-ipv6? stream* 'addr:port'+::
+    A TCP socket client. (See the forms for +'addr'+ below)
+
++*socket ?-ipv6? stream.server* '?addr:?port'+::
+    A TCP socket server (+'addr'+ defaults to +0.0.0.0+ for IPv4 or +[::]+ for IPv6).
+
++*socket ?-ipv6? dgram* ?'addr:port'?+::
+    A UDP socket client. If the address is not specified,
+    the client socket will be unbound and 'sendto' must be used
+    to indicated the destination.
+
++*socket ?-ipv6? dgram.server* 'addr:port'+::
+    A UDP socket server.
+
++*socket pipe*+::
+    A pipe. Note that unlike all other socket types, this command returns
+    a list of two channels: {read write}
+
++*socket pair*+::
+    A socketpair (see socketpair(2)). Like `socket pipe`, this command returns
+    a list of two channels: {s1 s2}. These channels are both readable and writable.
+
+This command creates a socket connected (client) or bound (server) to the given
+address.
+
+The returned value is channel and may generally be used with the various file I/O
+commands (gets, puts, read, etc.), either as object-based syntax or Tcl-compatible syntax.
+
+    set f [socket stream www.google.com:80]
+    aio.sockstream1
+    $f puts -nonewline "GET / HTTP/1.0\r\n\r\n"
+    $f gets
+    HTTP/1.0 302 Found
+    $f close
+
+Server sockets, however support only 'accept', which is most useful in conjunction with
+the EVENTLOOP API.
+
+    set f [socket stream.server 80]
+    $f readable {
+        set client [$f accept]
+        $client gets $buf
+        ...
+        $client puts -nonewline "HTTP/1.1 404 Not found\r\n"
+        $client close
+    }
+    vwait done
+
+The address, +'addr'+, can be given in one of the following forms:
+
+1. For IPv4 socket types, an IPv4 address such as 192.168.1.1
+2. For IPv6 socket types, an IPv6 address such as [fe80::1234] or [::]
+3. A hostname
+
+Note that on many systems, listening on an IPv6 address such as [::] will
+also accept requests via IPv4.
+
+Where a hostname is specified, the +'first'+ returned address is used
+which matches the socket type is used.
+
+The special type 'pipe' isn't really a socket.
+
+    lassign [socket pipe] r w
+
+    # Must close $w after exec
+    exec ps >@$w &
+    $w close
+
+    $r readable ...
+
+syslog
+~~~~~~
++*syslog* '?options? ?priority? message'+
+
+This  command sends message to system syslog facility with given
+priority. Valid priorities are:
+
+    emerg, alert, crit, err, error, warning, notice, info, debug
+
+If a message is specified, but no priority is specified, then a
+priority of info is used.
+
+By default, facility user is used and the value of global tcl variable
+argv0 is used as ident string. However, any of the following options
+may be specified before priority to control these parameters:
+
++*-facility* 'value'+::
+    Use specified facility instead of user. The following
+    values for facility are recognized:
+
+    authpriv, cron, daemon, kernel, lpr, mail, news, syslog, user,
+    uucp, local0-local7
+
++*-ident* 'string'+::
+    Use given string instead of argv0 variable for ident string.
+
++*-options* 'integer'+::
+    Set syslog options such as +LOG_CONS+, +LOG_NDELAY+. You should
+    use numeric values of those from your system syslog.h file,
+    because I haven't got time to implement yet another hash
+    table.
+
+pack: pack, unpack
+~~~~~~~~~~~~~~~~~~
+The optional 'pack' extension provides commands to encode and decode binary strings.
+
++*pack* 'varName value' *-intle|-intbe|-floatle|-floatbe|-str* 'bitwidth ?bitoffset?'+::
+    Packs the binary representation of +'value'+ into the variable
+    +'varName'+. The value is packed according to the given type
+    (integer/floating point/string, big-endian/little-endian), width and bit offset.
+    The variable is created if necessary (like `append`).
+    Ihe variable is expanded if necessary.
+
++*unpack* 'binvalue' *-intbe|-intle|-uintbe|-uintle|-floatbe|-floatle|-str* 'bitpos bitwidth'+::
+    Unpacks bits from +'binvalue'+ at bit position +'bitpos'+ and with +'bitwidth'+.
+    Interprets the value according to the type (integer/floating point/string, big-endian/little-endian
+    and signed/unsigned) and returns it. For integer types, +'bitwidth'+
+    may be up to the size of a Jim Tcl integer (typically 64 bits). For floating point types,
+    +'bitwidth'+ may be 32 bits (for single precision numbers) or 64 bits (for double precision).
+    For the string type, both the width and the offset must be on a byte boundary (multiple of 8). Attempting to
+    access outside the length of the value will return 0 for integer types, 0.0 for floating point types
+    or the empty string for the string type.
+
+binary
+~~~~~~
+The optional, pure-Tcl 'binary' extension provides the Tcl-compatible `binary scan` and `binary format`
+commands based on the low-level `pack` and `unpack` commands.
+
+See the Tcl documentation at: http://www.tcl.tk/man/tcl8.5/TclCmd/binary.htm
+
+Note that 'binary format' with f/r/R specifiers (single-precision float) uses the value of Infinity
+ in case of overflow.
+
+oo: class, super
+~~~~~~~~~~~~~~~~
+The optional, pure-Tcl 'oo' extension provides object-oriented (OO) support for Jim Tcl.
+
+See the online documentation (http://jim.tcl.tk/index.html/doc/www/www/documentation/oo/) for more details.
+
++*class* 'classname ?baseclasses? classvars'+::
+    Create a new class, +'classname'+, with the given dictionary
+    (+'classvars'+) as class variables. These are the initial variables
+    which all newly created objects of this class are initialised with.
+    If a list of baseclasses is given, methods and instance variables
+    are inherited.
+
++*super* 'method ?args \...?'+::
+    From within a method, invokes the given method on the base class.
+    Note that this will only call the last baseclass given.
+
+tree
+~~~~
+The optional, pure-Tcl 'tree' extension implements an OO, general purpose tree structure
+similar to that provided by tcllib ::struct::tree (http://tcllib.sourceforge.net/doc/struct_tree.html)
+
+A tree is a collection of nodes, where each node (except the root node) has a single parent
+and zero or more child nodes (ordered), as well as zero or more attribute/value pairs.
+
++*tree*+::
+    Creates and returns a new tree object with a single node named "root".
+    All operations on the tree are invoked through this object.
+
++$tree *destroy*+::
+    Destroy the tree and all it's nodes. (Note that the the tree will also
+    be automatically garbage collected once it goes out of scope).
+
++$tree *set* 'nodename key value'+::
+    Set the value for the given attribute key.
+
++$tree *lappend* 'nodename key value \...'+::
+    Append to the (list) value(s) for the given attribute key, or set if not yet set.
+
++$tree *keyexists* 'nodename key'+::
+    Returns 1 if the given attribute key exists.
+
++$tree *get* 'nodename key'+::
+    Returns the value associated with the given attribute key.
+
++$tree *getall* 'nodename'+::
+    Returns the entire attribute dictionary associated with the given key.
+
++$tree *depth* 'nodename'+::
+    Returns the depth of the given node. The depth of "root" is 0.
+
++$tree *parent* 'nodename'+::
+    Returns the node name of the parent node, or "" for the root node.
+
++$tree *numchildren* 'nodename'+::
+    Returns the number of child nodes.
+
++$tree *children* 'nodename'+::
+    Returns a list of the child nodes.
+
++$tree *next* 'nodename'+::
+    Returns the next sibling node, or "" if none.
+
++$tree *insert* 'nodename ?index?'+::
+    Add a new child node to the given node. The index is a list index
+    such as +3+ or +end-2+. The default index is +end+.
+    Returns the name of the newly added node.
+
++$tree *walk* 'nodename' *dfs|bfs* {'actionvar nodevar'} 'script'+::
+    Walks the tree starting from the given node, either breadth first (+bfs+)
+    depth first (+dfs+).
+    The value +"enter"+ or +"exit"+ is stored in variable +'actionvar'+.
+    The name of each node is stored in +'nodevar'+.
+    The script is evaluated twice for each node, on entry and exit.
+
++$tree *dump*+::
+    Dumps the tree contents to stdout
+
+tcl::prefix
+~~~~~~~~~~~
+The optional tclprefix extension provides the Tcl8.6-compatible 'tcl::prefix' command
+(http://www.tcl.tk/man/tcl8.6/TclCmd/prefix.htm) for matching strings against a table
+of possible values (typically commands or options).
+
++*tcl::prefix all* 'table string'+::
+    Returns a list of all elements in +'table'+ that begin with the prefix +'string'+.
+
++*tcl::prefix longest* 'table string'+::
+    Returns the longest common prefix of all elements in +'table'+ that begin with the prefix +'string'+.
+
++*tcl::prefix match* '?options? table string'+::
+    If +'string'+ equals one element in +'table'+ or is a prefix to
+    exactly one element, the matched element is returned. If not, the
+    result depends on the +-error+ option.
+
+    * +*-exact*+ Accept only exact matches.
+    * +*-message* 'string'+ Use +'string'+ in the error message at a mismatch. Default is "option".
+    * +*-error* 'options'+ The options are used when no match is found. If +'options'+ is
+      empty, no error is generated and an empty string is returned.
+      Otherwise the options are used as return options when
+      generating the error message. The default corresponds to
+      setting +-level 0+.
+
+history
+~~~~~~~
+The optional history extension provides script access to the command line editing
+and history support available in 'jimsh'. See 'examples/jtclsh.tcl' for an example.
+Note: if line editing support is not available, `history getline` acts like `gets` and
+the remaining subcommands do nothing.
+
++*history load* 'filename'+::
+    Load history from a (text) file. If the file does not exist or is not readable,
+    it is ignored.
+
++*history getline* 'prompt ?varname?'+::
+    Displays the given prompt and allows a line to be entered. Similarly to `gets`,
+    if +'varname'+ is given, it receives the line and the length of the line is returned,
+    or -1 on EOF. If +'varname'+ is not given, the line is returned directly.
+
++*history add* 'line'+::
+    Adds the given line to the history buffer.
+
++*history save* 'filename'+::
+    Saves the current history buffer to the given file.
+
++*history show*+::
+    Displays the current history buffer to standard output.
+
+namespace
+~~~~~~~~~
+Provides namespace-related functions. See also: http://www.tcl.tk/man/tcl8.6/TclCmd/namespace.htm
+
++*namespace code* 'script'+::
+    Captures the current namespace context for later execution of
+    the script +'script'+. It returns a new script in which script has
+    been wrapped in a +*namespace inscope*+ command.
+
++*namespace current*+::
+    Returns the fully-qualified name for the current namespace.
+
++*namespace delete* '?namespace ...?'+::
+    Deletes all commands and variables with the given namespace prefixes.
+
++*namespace eval* 'namespace arg ?arg...?'+::
+    Activates a namespace called +'namespace'+ and evaluates some code in that context.
+
++*namespace origin* 'command'+::
+    Returns the fully-qualified name of the original command to which the imported command +'command'+ refers.
+
++*namespace parent* ?namespace?+::
+    Returns the fully-qualified name of the parent namespace for namespace +'namespace'+, if given, otherwise
+    for the current namespace.
+
++*namespace qualifiers* 'string'+::
+    Returns any leading namespace qualifiers for +'string'+
+
++*namespace tail* 'string'+::
+    Returns the simple name at the end of a qualified string.
+
++*namespace upvar* 'namespace ?arg...?'+::
+    This command arranges for zero or more local variables in the current procedure to refer to variables in +'namespace'+
+
++*namespace which* '?-command|-variable? name'+::
+    Looks up +'name'+ as either a command (the default) or variable and returns its fully-qualified name.
+
+[[BuiltinVariables]]
+BUILT-IN VARIABLES
+------------------
+
+The following global variables are created automatically
+by the Tcl library.
+
++*env*+::
+    This variable is set by Jim as an array
+    whose elements are the environment variables for the process.
+    Reading an element will return the value of the corresponding
+    environment variable.
+    This array is initialised at startup from the `env` command.
+    It may be modified and will affect the environment passed to
+    commands invoked with `exec`.
+
++*platform_tcl*+::
+    This variable is set by Jim as an array containing information
+    about the platform on which Jim was built. Currently this includes
+    'os' and 'platform'.
+
++*auto_path*+::
+    This variable contains a list of paths to search for packages.
+    It defaults to a location based on where jim is installed
+    (e.g. +/usr/local/lib/jim+), but may be changed by +jimsh+
+    or the embedding application. Note that +jimsh+ will consider
+    the environment variable +$JIMLIB+ to be a list of colon-separated
+    list of paths to add to +*auto_path*+.
+
++*errorCode*+::
+    This variable holds the value of the -errorcode return
+    option set by the most recent error that occurred in this
+    interpreter. This list value represents additional information
+    about the error in a form that is easy to process with
+    programs. The first element of the list identifies a general
+    class of errors, and determines the format of the rest of
+    the list. The following formats for -errorcode return options
+    are used by the Tcl core; individual applications may define
+    additional formats. Currently only `exec` sets this variable.
+    Otherwise it will be +NONE+.
+
+The following global variables are set by jimsh.
+
++*tcl_interactive*+::
+    This variable is set to 1 if jimsh is started in interactive mode
+    or 0 otherwise.
+
++*tcl_platform*+::
+    This variable is set by Jim as an array containing information
+    about the platform upon which Jim was built. The following is an
+    example of the contents of this array.
+
+    tcl_platform(byteOrder)     = littleEndian
+    tcl_platform(os)            = Darwin
+    tcl_platform(platform)      = unix
+    tcl_platform(pointerSize)   = 8
+    tcl_platform(threaded)      = 0
+    tcl_platform(wordSize)      = 8
+    tcl_platform(pathSeparator) = :
+
++*argv0*+::
+    If jimsh is invoked to run a script, this variable contains the name
+    of the script.
+
++*argv*+::
+    If jimsh is invoked to run a script, this variable contains a list
+    of any arguments supplied to the script.
+
++*argc*+::
+    If jimsh is invoked to run a script, this variable contains the number
+    of arguments supplied to the script.
+
++*jim_argv0*+::
+    The value of argv[0] when jimsh was invoked.
+
+CHANGES IN PREVIOUS RELEASES
+----------------------------
+
+=== In v0.70 ===
+
+1. +platform_tcl()+ settings are now automatically determined
+2. Add aio `$handle filename`
+3. Add `info channels`
+4. The 'bio' extension is gone. Now `aio` supports 'copyto'.
+5. Add `exists` command
+6. Add the pure-Tcl 'oo' extension
+7. The `exec` command now only uses vfork(), not fork()
+8. Unit test framework is less verbose and more Tcl-compatible
+9. Optional UTF-8 support
+10. Optional built-in regexp engine for better Tcl compatibility and UTF-8 support
+11. Command line editing in interactive mode, e.g. 'jimsh'
+
+=== In v0.63 ===
+
+1. `source` now checks that a script is complete (.i.e. not missing a brace)
+2. 'info complete' now uses the real parser and so is 100% accurate
+3. Better access to live stack frames with 'info frame', `stacktrace` and `stackdump`
+4. `tailcall` no longer loses stack trace information
+5. Add `alias` and `curry`
+6. `lambda`, `alias` and `curry` are implemented via `tailcall` for efficiency
+7. `local` allows procedures to be deleted automatically at the end of the current procedure
+8. udp sockets are now supported for both clients and servers.
+9. vfork-based exec is now working correctly
+10. Add 'file tempfile'
+11. Add 'socket pipe'
+12. Enhance 'try ... on ... finally' to be more Tcl 8.6 compatible
+13. It is now possible to `return` from within `try`
+14. IPv6 support is now included
+15. Add 'string is'
+16. Event handlers works better if an error occurs. eof handler has been removed.
+17. `exec` now sets $::errorCode, and catch sets opts(-errorcode) for exit status
+18. Command pipelines via open "|..." are now supported
+19. `pid` can now return pids of a command pipeline
+20. Add 'info references'
+21. Add support for 'after +'ms'+', 'after idle', 'after info', `update`
+22. `exec` now sets environment based on $::env
+23. Add 'dict keys'
+24. Add support for 'lsort -index'
+
+=== In v0.62 ===
+
+1. Add support to `exec` for '>&', '>>&', '|&', '2>@1'
+2. Fix `exec` error messages when special token (e.g. '>') is the last token
+3. Fix `subst` handling of backslash escapes.
+4. Allow abbreviated options for `subst`
+5. Add support for `return`, `break`, `continue` in subst
+6. Many `expr` bug fixes
+7. Add support for functions in `expr` (e.g. int(), abs()), and also 'in', 'ni' list operations
+8. The variable name argument to `regsub` is now optional
+9. Add support for 'unset -nocomplain'
+10. Add support for list commands: `lassign`, `lrepeat`
+11. Fully-functional `lsearch` is now implemented
+12. Add 'info nameofexecutable' and 'info returncodes'
+13. Allow `catch` to determine what return codes are caught
+14. Allow `incr` to increment an unset variable by first setting to 0
+15. Allow 'args' and optional arguments to the left or required arguments in `proc`
+16. Add 'file copy'
+17. Add 'try ... finally' command
+
+
+LICENCE
+-------
+
+ Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
+ Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
+ Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
+ Copyright 2008 oharboe - Oyvind Harboe - oyvind.harboe@zylin.com
+ Copyright 2008 Andrew Lunn <andrew@lunn.ch>
+ Copyright 2008 Duane Ellis <openocd@duaneellis.com>
+ Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
+ Copyright 2009 Steve Bennett <steveb@workware.net.au>
+
+[literal]
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following
+    disclaimer in the documentation and/or other materials
+    provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ The views and conclusions contained in the software and documentation
+ are those of the authors and should not be interpreted as representing
+ official policies, either expressed or implied, of the Jim Tcl Project.
diff --git a/jim/jimautoconf.h.in b/jim/jimautoconf.h.in
deleted file mode 100644 (file)
index f4eb0e5..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/* jimautoconf.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Define to 1 if you have the `backtrace' function. */
-#undef HAVE_BACKTRACE
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Have the dlopen function */
-#undef HAVE_DLOPEN
-
-/* Define to 1 if you have the `fork' function. */
-#undef HAVE_FORK
-
-/* Define to 1 if you have the `getaddrinfo' function. */
-#undef HAVE_GETADDRINFO
-
-/* Define to 1 if you have the `geteuid' function. */
-#undef HAVE_GETEUID
-
-/* Define to 1 if you have the `inet_ntop' function. */
-#undef HAVE_INET_NTOP
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if the system has the type `long long'. */
-#undef HAVE_LONG_LONG
-
-/* Define to 1 if you have the `lstat' function. */
-#undef HAVE_LSTAT
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `mkstemp' function. */
-#undef HAVE_MKSTEMP
-
-/* Define to 1 if you have the `opendir' function. */
-#undef HAVE_OPENDIR
-
-/* Define to 1 if you have the `pipe' function. */
-#undef HAVE_PIPE
-
-/* Have libreadline */
-#undef HAVE_READLINE
-
-/* Define to 1 if you have the `readlink' function. */
-#undef HAVE_READLINK
-
-/* Define to 1 if you have the `realpath' function. */
-#undef HAVE_REALPATH
-
-/* Define to 1 if you have the `regcomp' function. */
-#undef HAVE_REGCOMP
-
-/* Define to 1 if you have the `sigaction' function. */
-#undef HAVE_SIGACTION
-
-/* Define to 1 if you have the `sleep' function. */
-#undef HAVE_SLEEP
-
-/* Have libsqlite */
-#undef HAVE_SQLITE
-
-/* Have libsqlite3 */
-#undef HAVE_SQLITE3
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strptime' function. */
-#undef HAVE_STRPTIME
-
-/* Define to 1 if you have the `sysinfo' function. */
-#undef HAVE_SYSINFO
-
-/* Define to 1 if you have the `syslog' function. */
-#undef HAVE_SYSLOG
-
-/* Define to 1 if you have the `sys_siglist' function. */
-#undef HAVE_SYS_SIGLIST
-
-/* Define to 1 if you have the `sys_signame' function. */
-#undef HAVE_SYS_SIGNAME
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-#undef HAVE_SYS_UN_H
-
-/* Define to 1 if you have the <termios.h> header file. */
-#undef HAVE_TERMIOS_H
-
-/* Define to 1 if you have the `ualarm' function. */
-#undef HAVE_UALARM
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the `usleep' function. */
-#undef HAVE_USLEEP
-
-/* Define to 1 if you have the `vfork' function. */
-#undef HAVE_VFORK
-
-/* Define to 1 if you have the `waitpid' function. */
-#undef HAVE_WAITPID
-
-/* No need to declare extern 'environ'. */
-#undef NO_ENVIRON_EXTERN
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
index c652ad4..f1b7cd3 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * vi:se ts=8:
+ *
  * regcomp and regexec -- regsub and regerror are elsewhere
  *
  *     Copyright (c) 1986 by University of Toronto.
  * precedence is structured in regular expressions.  Serious changes in
  * regular-expression syntax might require a total rethink.
  */
+
+#include "jimautoconf.h"
+
+#if defined(JIM_REGEXP)
 #include <stdio.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "jim.h"
-#include "jimautoconf.h"
 #include "jimregexp.h"
 #include "utf8.h"
 
-#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP)
+/* An arbitrary limit, but this seems enough. Must be less than 1000. */
+#define REG_MAX_PAREN 100
 
 /*
  * Structure for regexp "program".  This is essentially a linear encoding
  * to the thing following the set of BRANCHes.)  The opcodes are:
  */
 
-/* This *MUST* be less than (255-20)/2=117 */
-#define REG_MAX_PAREN 100
-
-/* definition  number  opnd?   meaning */
+/* definition          number  opnd?   meaning */
 #define        END     0       /* no   End of program. */
 #define        BOL     1       /* no   Match "" at beginning of line. */
 #define        EOL     2       /* no   Match "" at end of line. */
 #define        BACK    7       /* no   Match "", "next" ptr points backward. */
 #define        EXACTLY 8       /* str  Match this string. */
 #define        NOTHING 9       /* no   Match empty string. */
-#define        REP             10      /* max,min      Match this (simple) thing [min,max] times. */
-#define        REPMIN  11      /* max,min      Match this (simple) thing [min,max] times, mininal match. */
+#define        REP     10      /* max,min      Match this (simple) thing [min,max] times. */
+#define        REPMIN  11      /* max,min      Match this (simple) thing [min,max] times, minimal match. */
 #define        REPX    12      /* max,min      Match this (complex) thing [min,max] times. */
 #define        REPXMIN 13      /* max,min      Match this (complex) thing [min,max] times, minimal match. */
 
 #define        WORDA   15      /* no   Match "" at wordchar, where prev is nonword */
 #define        WORDZ   16      /* no   Match "" at nonwordchar, where prev is word */
-#define        OPEN    20      /* no   Mark this point in input as start of #n. */
+
+#define        OPENNC  1000    /* no   Non-capturing parentheses - must be OPEN-1 */
+#define        OPEN    1001    /* no   Mark this point in input as start of #n. */
                        /*      OPEN+1 is number 1, etc. */
-#define        CLOSE   (OPEN+REG_MAX_PAREN)    /* no   Analogous to OPEN. */
+
+/* must not be any other opts between OPEN and CLOSE */
+
+#define        CLOSENC 2000    /* no   Non-capturing parentheses - must be CLOSE-1 */
+#define        CLOSE   2001    /* no   Analogous to OPEN. */
 #define        CLOSE_END       (CLOSE+REG_MAX_PAREN)
 
 /*
- * The first byte of the regexp internal "program" is actually this magic
- * number; the start node begins in the second byte.
+ * The first word of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second word.
  */
 #define        REG_MAGIC       0xFADED00D
 
  * BACK                Normal "next" pointers all implicitly point forward; BACK
  *             exists to make loop structures possible.
  *
- * STAR,PLUS   '?', and complex '*' and '+', are implemented as circular
- *             BRANCH structures using BACK.  Simple cases (one character
- *             per match) are implemented with STAR and PLUS for speed
- *             and to minimize recursive plunges.
+ * REP,REPX    Repeated matches ('?', '*', '+' and {min,max}) are implemented
+ *              as either simple repeats (REP) or complex repeats (REPX).
+ *              These opcodes include a "min" and "max" count after the opcode.
+ *             This is followed by a fourth "current count" word that is
+ *             only used by REPX, as it implements a recursive match.
+ *             REPMIN and REPXMIN are identical except they implement minimal repeats.
  *
  * OPEN,CLOSE  ...are numbered at compile time.
  */
 
 /*
- * A node is one char of opcode followed by two chars of "next" pointer.
- * "Next" pointers are stored as two 8-bit pieces, high order first.  The
- * value is a positive offset from the opcode of the node containing it.
+ * A node is one word of opcode followed by one word of "next" pointer.
+ * The "next" pointer value is a positive offset from the opcode of the node
+ * containing it.
  * An operand, if any, simply follows the node.  (Note that much of the
  * code generation knows about this implicit relationship.)
- *
- * Using two bytes for the "next" pointer is vast overkill for most things,
- * but allows patterns to get big without disasters.
  */
 #define        OP(preg, p)     (preg->program[p])
 #define        NEXT(preg, p)   (preg->program[p + 1])
 
 #define        FAIL(R,M)       { (R)->err = (M); return (M); }
 #define        ISMULT(c)       ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
-#define        META    "^$.[()|?{+*"
+#define        META            "^$.[()|?{+*"
 
 /*
  * Flags to be passed up and down.
  */
-#define        HASWIDTH        01      /* Known never to match null string. */
-#define        SIMPLE          02      /* Simple enough to be STAR/PLUS operand. */
-#define        SPSTART         04      /* Starts with * or +. */
+#define        HASWIDTH              /* Known never to match null string. */
+#define        SIMPLE                /* Simple enough to be STAR/PLUS operand. */
+#define        SPSTART               /* Starts with * or +. */
 #define        WORST           0       /* Worst case. */
 
 #define MAX_REP_COUNT 1000000
@@ -179,9 +187,9 @@ static int regnode(regex_t *preg, int op );
 static int regnext(regex_t *preg, int p );
 static void regc(regex_t *preg, int b );
 static int reginsert(regex_t *preg, int op, int size, int opnd );
-static void regtail_(regex_t *preg, int p, int val, int line );
+static void regtail(regex_t *preg, int p, int val);
 static void regoptail(regex_t *preg, int p, int val );
-#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__)
+static int regopsize(regex_t *preg, int p );
 
 static int reg_range_find(const int *string, int c);
 static const char *str_find(const char *string, int c, int nocase);
@@ -189,7 +197,7 @@ static int prefix_cmp(const int *prog, int proglen, const char *string, int noca
 
 /*#define DEBUG*/
 #ifdef DEBUG
-int regnarrate = 0;
+static int regnarrate = 0;
 static void regdump(regex_t *preg);
 static const char *regprop( int op );
 #endif
@@ -240,17 +248,12 @@ int regcomp(regex_t *preg, const char *exp, int cflags)
        /* First pass: determine size, legality. */
        preg->cflags = cflags;
        preg->regparse = exp;
-       /* XXX: For now, start unallocated */
-       preg->program = NULL;
-       preg->proglen = 0;
 
-#if 1
        /* Allocate space. */
        preg->proglen = (strlen(exp) + 1) * 5;
        preg->program = malloc(preg->proglen * sizeof(int));
        if (preg->program == NULL)
                FAIL(preg, REG_ERR_NOMEM);
-#endif
 
        /* Note that since we store a magic value as the first item in the program,
         * program offsets will never be 0
@@ -333,7 +336,14 @@ static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp )
 
        /* Make an OPEN node, if parenthesized. */
        if (paren) {
-               parno = ++preg->re_nsub;
+               if (preg->regparse[0] == '?' && preg->regparse[1] == ':') {
+                       /* non-capturing paren */
+                       preg->regparse += 2;
+                       parno = -1;
+               }
+               else {
+                       parno = ++preg->re_nsub;
+               }
                ret = regnode(preg, OPEN+parno);
        } else
                ret = 0;
@@ -436,7 +446,6 @@ static int regpiece(regex_t *preg, int *flagp)
        char op;
        int next;
        int flags;
-       int chain = 0;
        int min;
        int max;
 
@@ -519,7 +528,7 @@ static int regpiece(regex_t *preg, int *flagp)
                return 0;
        }
 
-       return chain ? chain : ret;
+       return ret;
 }
 
 /**
@@ -625,7 +634,23 @@ static int reg_decode_escape(const char *s, int *ch)
                case 't': *ch = '\t'; break;
                case 'v': *ch = '\v'; break;
                case 'u':
-                       if ((n = parse_hex(s, 4, ch)) > 0) {
+                       if (*s == '{') {
+                               /* Expect \u{NNNN} */
+                               n = parse_hex(s + 1, 6, ch);
+                               if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) {
+                                       s += n + 2;
+                               }
+                               else {
+                                       /* Invalid, so just treat as an escaped 'u' */
+                                       *ch = 'u';
+                               }
+                       }
+                       else if ((n = parse_hex(s, 4, ch)) > 0) {
+                               s += n;
+                       }
+                       break;
+               case 'U':
+                       if ((n = parse_hex(s, 8, ch)) > 0) {
                                s += n;
                        }
                        break;
@@ -702,7 +727,7 @@ static int regatom(regex_t *preg, int *flagp)
                                                return 0;
                                        }
                                }
-                               if (pattern[0] == '-' && pattern[1]) {
+                               if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') {
                                        /* skip '-' */
                                        pattern += utf8_tounicode(pattern, &end);
                                        pattern += reg_utf8_tounicode_case(pattern, &end, nocase);
@@ -906,6 +931,7 @@ static int regnode(regex_t *preg, int op)
 {
        reg_grow(preg, 2);
 
+       /* The OP followed by a next pointer */
        preg->program[preg->p++] = op;
        preg->program[preg->p++] = 0;
 
@@ -947,7 +973,7 @@ static int reginsert(regex_t *preg, int op, int size, int opnd )
 /*
  - regtail - set the next-pointer at the end of a node chain
  */
-static void regtail_(regex_t *preg, int p, int val, int line )
+static void regtail(regex_t *preg, int p, int val)
 {
        int scan;
        int temp;
@@ -1021,16 +1047,13 @@ int regexec(regex_t  *preg,  const  char *string, size_t nmatch, regmatch_t pmat
        preg->nmatch = nmatch;
        preg->start = string;   /* All offsets are computed from here */
 
-       /* Must clear out the embedded repeat counts */
-       for (scan = OPERAND(1); scan != 0; scan = regnext(preg, scan)) {
-               switch (OP(preg, scan)) {
-               case REP:
-               case REPMIN:
-               case REPX:
-               case REPXMIN:
-                       preg->program[scan + 4] = 0;
+       /* Must clear out the embedded repeat counts of REPX and REPXMIN opcodes */
+       for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) {
+               int op = OP(preg, scan);
+               if (op == END)
                        break;
-               }
+               if (op == REPX || op == REPXMIN)
+                       preg->program[scan + 4] = 0;
        }
 
        /* If there is a "must appear" string, look for it. */
@@ -1056,8 +1079,7 @@ int regexec(regex_t  *preg,  const  char *string, size_t nmatch, regmatch_t pmat
                        goto nextline;
                }
                while (1) {
-                       int ret = regtry(preg, string);
-                       if (ret) {
+                       if (regtry(preg, string)) {
                                return REG_NOERROR;
                        }
                        if (*string) {
@@ -1093,7 +1115,10 @@ nextline:
                        if (*s == '\0') {
                                break;
                        }
-                       s += utf8_charlen(*s);
+                       else {
+                               int c;
+                               s += utf8_tounicode(s, &c);
+                       }
                }
 
        /* Failure. */
@@ -1328,6 +1353,7 @@ static int regmatch(regex_t *preg, int prog)
 {
        int scan;       /* Current node. */
        int next;               /* Next node. */
+       const char *save;
 
        scan = prog;
 
@@ -1416,23 +1442,20 @@ static int regmatch(regex_t *preg, int prog)
                        break;
                case BACK:
                        break;
-               case BRANCH: {
-                               const char *save;
-
-                               if (OP(preg, next) != BRANCH)           /* No choice. */
-                                       next = OPERAND(scan);   /* Avoid recursion. */
-                               else {
-                                       do {
-                                               save = preg->reginput;
-                                               if (regmatch(preg, OPERAND(scan))) {
-                                                       return(1);
-                                               }
-                                               preg->reginput = save;
-                                               scan = regnext(preg, scan);
-                                       } while (scan != 0 && OP(preg, scan) == BRANCH);
-                                       return(0);
-                                       /* NOTREACHED */
-                               }
+               case BRANCH:
+                       if (OP(preg, next) != BRANCH)           /* No choice. */
+                               next = OPERAND(scan);   /* Avoid recursion. */
+                       else {
+                               do {
+                                       save = preg->reginput;
+                                       if (regmatch(preg, OPERAND(scan))) {
+                                               return(1);
+                                       }
+                                       preg->reginput = save;
+                                       scan = regnext(preg, scan);
+                               } while (scan != 0 && OP(preg, scan) == BRANCH);
+                               return(0);
+                               /* NOTREACHED */
                        }
                        break;
                case REP:
@@ -1444,36 +1467,31 @@ static int regmatch(regex_t *preg, int prog)
                        return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN);
 
                case END:
-                       return(1);      /* Success! */
-                       break;
+                       return 1;       /* Success! */
+
+               case OPENNC:
+               case CLOSENC:
+                       return regmatch(preg, next);
+
                default:
                        if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) {
-                               const char *save;
-
                                save = preg->reginput;
-
                                if (regmatch(preg, next)) {
-                                       int no;
-                                       /*
-                                        * Don't set startp if some later
-                                        * invocation of the same parentheses
-                                        * already has.
-                                        */
                                        if (OP(preg, scan) < CLOSE) {
-                                               no = OP(preg, scan) - OPEN;
+                                               int no = OP(preg, scan) - OPEN;
                                                if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) {
                                                        preg->pmatch[no].rm_so = save - preg->start;
                                                }
                                        }
                                        else {
-                                               no = OP(preg, scan) - CLOSE;
+                                               int no = OP(preg, scan) - CLOSE;
                                                if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) {
                                                        preg->pmatch[no].rm_eo = save - preg->start;
                                                }
                                        }
                                        return(1);
-                               } else
-                                       return(0);
+                               }
+                               return(0);
                        }
                        return REG_ERR_INTERNAL;
                }
@@ -1567,6 +1585,31 @@ static int regnext(regex_t *preg, int p )
                return(p+offset);
 }
 
+/*
+ - regopsize - returns the size of opcode + operands at 'p' in words
+ */
+static int regopsize(regex_t *preg, int p )
+{
+       /* Almost all opcodes are 2 words, but some are more */
+       switch (OP(preg, p)) {
+               case REP:
+               case REPMIN:
+               case REPX:
+               case REPXMIN:
+                       return 5;
+
+               case ANYOF:
+               case ANYBUT:
+               case EXACTLY: {
+                       int s = p + 2;
+                       while (preg->program[s++]) {
+                       }
+                       return s - p;
+               }
+       }
+       return 2;
+}
+
 #if defined(DEBUG) && !defined(JIM_BOOTSTRAP)
 
 /*
@@ -1577,12 +1620,12 @@ static void regdump(regex_t *preg)
        int s;
        int op = EXACTLY;       /* Arbitrary non-END op. */
        int next;
-       char buf[4];
+       char buf[MAX_UTF8_LEN + 1];
 
        int i;
        for (i = 1; i < preg->p; i++) {
-               printf("%02x ", preg->program[i]);
-               if (i % 16 == 15) {
+               printf("%02x ", (unsigned char)preg->program[i]);
+               if (i % 16 == 0) {
                        printf("\n");
                }
        }
@@ -1616,10 +1659,10 @@ static void regdump(regex_t *preg)
                        while (preg->program[s]) {
                                int len = preg->program[s++];
                                int first = preg->program[s++];
-                               buf[utf8_fromunicode(buf, first)] = 0;
+                               buf[utf8_getchars(buf, first)] = 0;
                                printf("%s", buf);
                                if (len > 1) {
-                                       buf[utf8_fromunicode(buf, first + len - 1)] = 0;
+                                       buf[utf8_getchars(buf, first + len - 1)] = 0;
                                        printf("-%s", buf);
                                }
                        }
@@ -1629,7 +1672,7 @@ static void regdump(regex_t *preg)
                        /* Literal string, where present. */
 
                        while (preg->program[s]) {
-                               buf[utf8_fromunicode(buf, preg->program[s])] = 0;
+                               buf[utf8_getchars(buf, preg->program[s])] = 0;
                                printf("%s", buf);
                                s++;
                        }
@@ -1641,7 +1684,7 @@ static void regdump(regex_t *preg)
        if (op == END) {
                /* Header fields of interest. */
                if (preg->regstart) {
-                       buf[utf8_fromunicode(buf, preg->regstart)] = 0;
+                       buf[utf8_getchars(buf, preg->regstart)] = 0;
                        printf("start '%s' ", buf);
                }
                if (preg->reganch)
@@ -1698,6 +1741,10 @@ static const char *regprop( int op )
                return "WORDA";
        case WORDZ:
                return "WORDZ";
+       case OPENNC:
+               return "OPEN";
+       case CLOSENC:
+               return "CLOSE";
        default:
                if (op >= OPEN && op < CLOSE) {
                        snprintf(buf, sizeof(buf), "OPEN%d", op-OPEN);
index 79a87e5..b7598d4 100644 (file)
@@ -1,27 +1,17 @@
 #ifndef JIMREGEXP_H
 #define JIMREGEXP_H
 
-#ifndef _JIMAUTOCONF_H
-#error Need jimautoconf.h
-#endif
-
-#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP)
-/* Use POSIX regex */
-#include <regex.h>
+/** regexp(3)-compatible regular expression implementation for Jim.
+ *
+ * See jimregexp.c for details
+ */
 
-#else
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #include <stdlib.h>
 
-/*
- * Definitions etc. for regexp(3) routines.
- *
- * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
- * not the System V one.
- *
- * 11/04/02 (seiwald) - const-ing for string literals
- */
-
 typedef struct {
        int rm_so;
        int rm_eo;
@@ -112,6 +102,8 @@ int regexec(regex_t  *preg,  const  char *string, size_t nmatch, regmatch_t pmat
 size_t regerror(int errcode, const regex_t *preg, char *errbuf,  size_t errbuf_size);
 void regfree(regex_t *preg);
 
+#ifdef __cplusplus
+}
 #endif
 
 #endif
index 2c94468..9c11083 100644 (file)
@@ -1,22 +1,36 @@
-
-/* Jimsh - An interactive shell for Jim
+/*
+ * jimsh - An interactive shell for Jim
+ *
  * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
  * Copyright 2009 Steve Bennett <steveb@workware.net.au>
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
  *
- * A copy of the license is also included in the source distribution
- * of Jim, as a TXT file name called LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
  */
 
 #include <stdio.h>
@@ -45,6 +59,12 @@ static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[])
     Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc));
 }
 
+static void JimPrintErrorMessage(Jim_Interp *interp)
+{
+    Jim_MakeErrorMessage(interp);
+    fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
+}
+
 int main(int argc, char *const argv[])
 {
     int retcode;
@@ -61,8 +81,7 @@ int main(int argc, char *const argv[])
 
     /* Register static extensions */
     if (Jim_InitStaticExtensions(interp) != JIM_OK) {
-        Jim_MakeErrorMessage(interp);
-        fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
+        JimPrintErrorMessage(interp);
     }
 
     Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]);
@@ -71,8 +90,7 @@ int main(int argc, char *const argv[])
 
     if (argc == 1) {
         if (retcode == JIM_ERR) {
-            Jim_MakeErrorMessage(interp);
-            fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
+            JimPrintErrorMessage(interp);
         }
         if (retcode != JIM_EXIT) {
             JimSetArgv(interp, 0, NULL);
@@ -93,8 +111,7 @@ int main(int argc, char *const argv[])
             retcode = Jim_EvalFile(interp, argv[1]);
         }
         if (retcode == JIM_ERR) {
-            Jim_MakeErrorMessage(interp);
-            fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
+            JimPrintErrorMessage(interp);
         }
     }
     if (retcode == JIM_EXIT) {
index 4065d06..e805356 100644 (file)
@@ -3,7 +3,8 @@
  *
  * You can find the latest source code at:
  *
- *   http://github.com/antirez/linenoise
+ *   http://github.com/msteveb/linenoise
+ *   (forked from http://github.com/antirez/linenoise)
  *
  * Does a number of crazy assumptions that happen to be true in 99.9999% of
  * the 2010 UNIX computers around.
@@ -12,6 +13,7 @@
  *
  * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
  * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2011, Steve Bennett <steveb at workware dot net dot au>
  *
  * All rights reserved.
  *
  * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
  * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
  *
- * Todo list:
- * - Win32 support
- * - Save and load history containing newlines
- *
  * Bloat:
  * - Completion?
  *
+ * Unix/termios
+ * ------------
  * List of escape sequences used by this program, we do everything just
  * a few sequences. In order to be so cheap we may have some
  * flickering effect with some slow terminal, but the lesser sequences
  * the more compatible.
  *
- * CHA (Cursor Horizontal Absolute)
- *    Sequence: ESC [ n G
- *    Effect: moves cursor to column n (1 based)
- *
  * EL (Erase Line)
  *    Sequence: ESC [ n K
  *    Effect: if n is 0 or missing, clear from cursor to end of line
  *    Sequence: ESC [ n C
  *    Effect: moves cursor forward of n chars
  *
+ * CR (Carriage Return)
+ *    Sequence: \r
+ *    Effect: moves cursor to column 1
+ *
  * The following are used to clear the screen: ESC [ H ESC [ 2 J
  * This is actually composed of two sequences:
  *
  * DSR/CPR (Report cursor position)
  *    Sequence: ESC [ 6 n
  *    Effect: reports current cursor position as ESC [ NNN ; MMM R
+ *
+ * win32/console
+ * -------------
+ * If __MINGW32__ is defined, the win32 console API is used.
+ * This could probably be made to work for the msvc compiler too.
+ * This support based in part on work by Jon Griffiths.
  */
 
-#ifdef __MINGW32__
+#ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
 #include <windows.h>
 #include <fcntl.h>
 #define USE_WINCONSOLE
+#ifdef __MINGW32__
+#define HAVE_UNISTD_H
+#else
+/* Microsoft headers don't like old POSIX names */
+#define strdup _strdup
+#define snprintf _snprintf
+#endif
 #else
 #include <termios.h>
 #include <sys/ioctl.h>
 #include <sys/poll.h>
 #define USE_TERMIOS
+#define HAVE_UNISTD_H
 #endif
 
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
-#include <unistd.h>
 
 #include "linenoise.h"
 
@@ -140,6 +155,9 @@ enum {
     SPECIAL_DELETE = -24,
     SPECIAL_HOME = -25,
     SPECIAL_END = -26,
+    SPECIAL_INSERT = -27,
+    SPECIAL_PAGE_UP = -28,
+    SPECIAL_PAGE_DOWN = -29
 };
 
 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
@@ -155,6 +173,7 @@ struct current {
     int pos;    /* Cursor position, measured in chars */
     int cols;   /* Size of the window, in chars */
     const char *prompt;
+    char *capture; /* Allocated capture buffer, or NULL for none. Always null terminated */
 #if defined(USE_TERMIOS)
     int fd;     /* Terminal fd */
 #elif defined(USE_WINCONSOLE)
@@ -177,6 +196,7 @@ void linenoiseHistoryFree(void) {
             free(history[j]);
         free(history);
         history = NULL;
+        history_len = 0;
     }
 }
 
@@ -194,7 +214,7 @@ static int isUnsupportedTerm(void) {
     if (term) {
         int j;
         for (j = 0; unsupported_term[j]; j++) {
-            if (strcasecmp(term, unsupported_term[j]) == 0) {
+            if (strcmp(term, unsupported_term[j]) == 0) {
                 return 1;
             }
         }
@@ -258,7 +278,10 @@ static void linenoiseAtExit(void) {
     linenoiseHistoryFree();
 }
 
-/* gcc/glibc insists that we care about the return code of write! */
+/* gcc/glibc insists that we care about the return code of write!
+ * Clarification: This means that a void-cast like "(void) (EXPR)"
+ * does not work.
+ */
 #define IGNORE_RC(EXPR) if (EXPR) {}
 
 /* This is fdprintf() on some systems, but use a different
@@ -283,7 +306,7 @@ static void clearScreen(struct current *current)
 
 static void cursorToLeft(struct current *current)
 {
-    fd_printf(current->fd, "\x1b[1G");
+    fd_printf(current->fd, "\r");
 }
 
 static int outputChars(struct current *current, const char *buf, int len)
@@ -293,7 +316,7 @@ static int outputChars(struct current *current, const char *buf, int len)
 
 static void outputControlChar(struct current *current, char ch)
 {
-    fd_printf(current->fd, "\033[7m^%c\033[0m", ch);
+    fd_printf(current->fd, "\x1b[7m^%c\x1b[0m", ch);
 }
 
 static void eraseEol(struct current *current)
@@ -303,7 +326,7 @@ static void eraseEol(struct current *current)
 
 static void setCursorPos(struct current *current, int x)
 {
-    fd_printf(current->fd, "\x1b[1G\x1b[%dC", x);
+    fd_printf(current->fd, "\r\x1b[%dC", x);
 }
 
 /**
@@ -364,6 +387,58 @@ static int fd_read(struct current *current)
 #endif
 }
 
+static int countColorControlChars(const char* prompt)
+{
+    /* ANSI color control sequences have the form:
+     * "\x1b" "[" [0-9;]* "m"
+     * We parse them with a simple state machine.
+     */
+
+    enum {
+        search_esc,
+        expect_bracket,
+        expect_trail
+    } state = search_esc;
+    int len = 0, found = 0;
+    char ch;
+
+    /* XXX: Strictly we should be checking utf8 chars rather than
+     *      bytes in case of the extremely unlikely scenario where
+     *      an ANSI sequence is part of a utf8 sequence.
+     */
+    while ((ch = *prompt++) != 0) {
+        switch (state) {
+        case search_esc:
+            if (ch == '\x1b') {
+                state = expect_bracket;
+            }
+            break;
+        case expect_bracket:
+            if (ch == '[') {
+                state = expect_trail;
+                /* 3 for "\e[ ... m" */
+                len = 3;
+                break;
+            }
+            state = search_esc;
+            break;
+        case expect_trail:
+            if ((ch == ';') || ((ch >= '0' && ch <= '9'))) {
+                /* 0-9, or semicolon */
+                len++;
+                break;
+            }
+            if (ch == 'm') {
+                found += len;
+            }
+            state = search_esc;
+            break;
+        }
+    }
+
+    return found;
+}
+
 static int getWindowSize(struct current *current)
 {
     struct winsize ws;
@@ -382,8 +457,8 @@ static int getWindowSize(struct current *current)
     if (current->cols == 0) {
         current->cols = 80;
 
-        /* Move cursor far right and report cursor position */
-        fd_printf(current->fd, "\x1b[999G" "\x1b[6n");
+        /* Move cursor far right and report cursor position, then back to the left */
+        fd_printf(current->fd, "\x1b[999C" "\x1b[6n");
 
         /* Parse the response: ESC [ rows ; cols R */
         if (fd_read_char(current->fd, 100) == 0x1b && fd_read_char(current->fd, 100) == '[') {
@@ -452,16 +527,28 @@ static int check_special(int fd)
                 return SPECIAL_HOME;
         }
     }
-    if (c == '[' && c2 >= '1' && c2 <= '6') {
+    if (c == '[' && c2 >= '1' && c2 <= '8') {
         /* extended escape */
-        int c3 = fd_read_char(fd, 50);
-        if (c2 == '3' && c3 == '~') {
-            /* delete char under cursor */
-            return SPECIAL_DELETE;
+        c = fd_read_char(fd, 50);
+        if (c == '~') {
+            switch (c2) {
+                case '2':
+                    return SPECIAL_INSERT;
+                case '3':
+                    return SPECIAL_DELETE;
+                case '5':
+                    return SPECIAL_PAGE_UP;
+                case '6':
+                    return SPECIAL_PAGE_DOWN;
+                case '7':
+                    return SPECIAL_HOME;
+                case '8':
+                    return SPECIAL_END;
+            }
         }
-        while (c3 != -1 && c3 != '~') {
+        while (c != -1 && c != '~') {
             /* .e.g \e[12~ or '\e[11;2~   discard the complete sequence */
-            c3 = fd_read_char(fd, 50);
+            c = fd_read_char(fd, 50);
         }
     }
 
@@ -510,7 +597,7 @@ static void clearScreen(struct current *current)
 
 static void cursorToLeft(struct current *current)
 {
-    COORD pos = { 0, current->y };
+    COORD pos = { 0, (SHORT)current->y };
     DWORD n;
 
     FillConsoleOutputAttribute(current->outh,
@@ -520,15 +607,17 @@ static void cursorToLeft(struct current *current)
 
 static int outputChars(struct current *current, const char *buf, int len)
 {
-    COORD pos = { current->x, current->y };
-    WriteConsoleOutputCharacter(current->outh, buf, len, pos, 0);
+    COORD pos = { (SHORT)current->x, (SHORT)current->y };
+    DWORD n;
+
+    WriteConsoleOutputCharacter(current->outh, buf, len, pos, &n);
     current->x += len;
     return 0;
 }
 
 static void outputControlChar(struct current *current, char ch)
 {
-    COORD pos = { current->x, current->y };
+    COORD pos = { (SHORT)current->x, (SHORT)current->y };
     DWORD n;
 
     FillConsoleOutputAttribute(current->outh, BACKGROUND_INTENSITY, 2, pos, &n);
@@ -538,7 +627,7 @@ static void outputControlChar(struct current *current, char ch)
 
 static void eraseEol(struct current *current)
 {
-    COORD pos = { current->x, current->y };
+    COORD pos = { (SHORT)current->x, (SHORT)current->y };
     DWORD n;
 
     FillConsoleOutputCharacter(current->outh, ' ', current->cols - current->x, pos, &n);
@@ -546,7 +635,7 @@ static void eraseEol(struct current *current)
 
 static void setCursorPos(struct current *current, int x)
 {
-    COORD pos = { x, current->y };
+    COORD pos = { (SHORT)x, (SHORT)current->y };
 
     SetConsoleCursorPosition(current->outh, pos);
     current->x = x;
@@ -575,12 +664,18 @@ static int fd_read(struct current *current)
                     return SPECIAL_UP;
                  case VK_DOWN:
                     return SPECIAL_DOWN;
+                 case VK_INSERT:
+                    return SPECIAL_INSERT;
                  case VK_DELETE:
                     return SPECIAL_DELETE;
                  case VK_HOME:
                     return SPECIAL_HOME;
                  case VK_END:
                     return SPECIAL_END;
+                 case VK_PRIOR:
+                    return SPECIAL_PAGE_UP;
+                 case VK_NEXT:
+                    return SPECIAL_PAGE_DOWN;
                 }
             }
             /* Note that control characters are already translated in AsciiChar */
@@ -596,6 +691,14 @@ static int fd_read(struct current *current)
     return -1;
 }
 
+static int countColorControlChars(const char* prompt)
+{
+    /* For windows we assume that there are no embedded ansi color
+     * control sequences.
+     */
+    return 0;
+}
+
 static int getWindowSize(struct current *current)
 {
     CONSOLE_SCREEN_BUFFER_INFO info;
@@ -614,16 +717,6 @@ static int getWindowSize(struct current *current)
 }
 #endif
 
-static int utf8_getchars(char *buf, int c)
-{
-#ifdef USE_UTF8
-    return utf8_fromunicode(buf, c);
-#else
-    *buf = c;
-    return 1;
-#endif
-}
-
 /**
  * Returns the unicode character at the given offset,
  * or -1 if none.
@@ -658,6 +751,11 @@ static void refreshLine(const char *prompt, struct current *current)
     plen = strlen(prompt);
     pchars = utf8_strlen(prompt, plen);
 
+    /* Scan the prompt for embedded ansi color control sequences and
+     * discount them as characters/columns.
+     */
+    pchars -= countColorControlChars(prompt);
+
     /* Account for a line which is too long to fit in the window.
      * Note that control chars require an extra column
      */
@@ -674,7 +772,7 @@ static void refreshLine(const char *prompt, struct current *current)
         }
     }
 
-    /* If too many are need, strip chars off the front of 'buf'
+    /* If too many are needed, strip chars off the front of 'buf'
      * until it fits. Note that if the current char is a control character,
      * we need one extra col.
      */
@@ -682,7 +780,7 @@ static void refreshLine(const char *prompt, struct current *current)
         n++;
     }
 
-    while (n >= current->cols) {
+    while (n >= current->cols && pos > 0) {
         b = utf8_tounicode(buf, &ch);
         if (ch < ' ') {
             n--;
@@ -825,16 +923,64 @@ static int insert_char(struct current *current, int pos, int ch)
 }
 
 /**
+ * Captures up to 'n' characters starting at 'pos' for the cut buffer.
+ *
+ * This replaces any existing characters in the cut buffer.
+ */
+static void capture_chars(struct current *current, int pos, int n)
+{
+    if (pos >= 0 && (pos + n - 1) < current->chars) {
+        int p1 = utf8_index(current->buf, pos);
+        int nbytes = utf8_index(current->buf + p1, n);
+
+        if (nbytes) {
+            free(current->capture);
+            /* Include space for the null terminator */
+            current->capture = (char *)malloc(nbytes + 1);
+            memcpy(current->capture, current->buf + p1, nbytes);
+            current->capture[nbytes] = '\0';
+        }
+    }
+}
+
+/**
+ * Removes up to 'n' characters at cursor position 'pos'.
+ *
  * Returns 0 if no chars were removed or non-zero otherwise.
  */
 static int remove_chars(struct current *current, int pos, int n)
 {
     int removed = 0;
+
+    /* First save any chars which will be removed */
+    capture_chars(current, pos, n);
+
     while (n-- && remove_char(current, pos)) {
         removed++;
     }
     return removed;
 }
+/**
+ * Inserts the characters (string) 'chars' at the cursor position 'pos'.
+ *
+ * Returns 0 if no chars were inserted or non-zero otherwise.
+ */
+static int insert_chars(struct current *current, int pos, const char *chars)
+{
+    int inserted = 0;
+
+    while (*chars) {
+        int ch;
+        int n = utf8_tounicode(chars, &ch);
+        if (insert_char(current, pos, ch) == 0) {
+            break;
+        }
+        inserted++;
+        pos++;
+        chars += n;
+    }
+    return inserted;
+}
 
 #ifndef NO_COMPLETION
 static linenoiseCompletionCallback *completionCallback = NULL;
@@ -919,7 +1065,7 @@ void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
 
 #endif
 
-static int linenoisePrompt(struct current *current) {
+static int linenoiseEdit(struct current *current) {
     int history_index = 0;
 
     /* The latest history entry is always our current buffer, that
@@ -937,7 +1083,7 @@ static int linenoisePrompt(struct current *current) {
         /* Only autocomplete when the callback is set. It returns < 0 when
          * there was an error reading from fd. Otherwise it will return the
          * character that should be handled next. */
-        if (c == 9 && completionCallback != NULL) {
+        if (c == '\t' && current->pos == current->chars && completionCallback != NULL) {
             c = completeLine(current);
             /* Return on errors */
             if (c < 0) return current->len;
@@ -974,12 +1120,18 @@ process_char:
                 free(history[history_len]);
                 return -1;
             }
-            /* Otherwise delete char to right of cursor */
-            if (remove_char(current, current->pos)) {
+            /* Otherwise fall through to delete char to right of cursor */
+        case SPECIAL_DELETE:
+            if (remove_char(current, current->pos) == 1) {
                 refreshLine(current->prompt, current);
             }
             break;
-        case ctrl('W'):    /* ctrl-w */
+        case SPECIAL_INSERT:
+            /* Ignore. Expansion Hook.
+             * Future possibility: Toggle Insert/Overwrite Modes
+             */
+            break;
+        case ctrl('W'):    /* ctrl-w, delete word at left. save deleted chars */
             /* eat any spaces on the left */
             {
                 int pos = current->pos;
@@ -1099,9 +1251,11 @@ process_char:
             }
             break;
         case ctrl('T'):    /* ctrl-t */
-            if (current->pos > 0 && current->pos < current->chars) {
-                c = get_char(current, current->pos);
-                remove_char(current, current->pos);
+            if (current->pos > 0 && current->pos <= current->chars) {
+                /* If cursor is at end, transpose the previous two chars */
+                int fixer = (current->pos == current->chars);
+                c = get_char(current, current->pos - fixer);
+                remove_char(current, current->pos - fixer);
                 insert_char(current, current->pos - 1, c);
                 refreshLine(current->prompt, current);
             }
@@ -1138,81 +1292,90 @@ process_char:
                 refreshLine(current->prompt, current);
             }
             break;
+        case SPECIAL_PAGE_UP:
+          dir = history_len - history_index - 1; /* move to start of history */
+          goto history_navigation;
+        case SPECIAL_PAGE_DOWN:
+          dir = -history_index; /* move to 0 == end of history, i.e. current */
+          goto history_navigation;
         case ctrl('P'):
         case SPECIAL_UP:
             dir = 1;
+          goto history_navigation;
         case ctrl('N'):
         case SPECIAL_DOWN:
+history_navigation:
             if (history_len > 1) {
                 /* Update the current history entry before to
                  * overwrite it with tne next one. */
-                free(history[history_len-1-history_index]);
-                history[history_len-1-history_index] = strdup(current->buf);
+                free(history[history_len - 1 - history_index]);
+                history[history_len - 1 - history_index] = strdup(current->buf);
                 /* Show the new entry */
                 history_index += dir;
                 if (history_index < 0) {
                     history_index = 0;
                     break;
                 } else if (history_index >= history_len) {
-                    history_index = history_len-1;
+                    history_index = history_len - 1;
                     break;
                 }
-                set_current(current, history[history_len-1-history_index]);
-                refreshLine(current->prompt, current);
-            }
-            break;
-
-        case SPECIAL_DELETE:
-            if (remove_char(current, current->pos) == 1) {
+                set_current(current, history[history_len - 1 - history_index]);
                 refreshLine(current->prompt, current);
             }
             break;
+        case ctrl('A'): /* Ctrl+a, go to the start of the line */
         case SPECIAL_HOME:
             current->pos = 0;
             refreshLine(current->prompt, current);
             break;
+        case ctrl('E'): /* ctrl+e, go to the end of the line */
         case SPECIAL_END:
             current->pos = current->chars;
             refreshLine(current->prompt, current);
             break;
-        default:
-            /* Only tab is allowed without ^V */
-            if (c == '\t' || c >= ' ') {
-                if (insert_char(current, current->pos, c) == 1) {
-                    refreshLine(current->prompt, current);
-                }
-            }
-            break;
-        case ctrl('U'): /* Ctrl+u, delete to beginning of line. */
+        case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
             if (remove_chars(current, 0, current->pos)) {
                 refreshLine(current->prompt, current);
             }
             break;
-        case ctrl('K'): /* Ctrl+k, delete from current to end of line. */
+        case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
             if (remove_chars(current, current->pos, current->chars - current->pos)) {
                 refreshLine(current->prompt, current);
             }
             break;
-        case ctrl('A'): /* Ctrl+a, go to the start of the line */
-            current->pos = 0;
-            refreshLine(current->prompt, current);
-            break;
-        case ctrl('E'): /* ctrl+e, go to the end of the line */
-            current->pos = current->chars;
-            refreshLine(current->prompt, current);
+        case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
+            if (current->capture && insert_chars(current, current->pos, current->capture)) {
+                refreshLine(current->prompt, current);
+            }
             break;
         case ctrl('L'): /* Ctrl+L, clear screen */
-            /* clear screen */
             clearScreen(current);
             /* Force recalc of window size for serial terminals */
             current->cols = 0;
             refreshLine(current->prompt, current);
             break;
+        default:
+            /* Only tab is allowed without ^V */
+            if (c == '\t' || c >= ' ') {
+                if (insert_char(current, current->pos, c) == 1) {
+                    refreshLine(current->prompt, current);
+                }
+            }
+            break;
         }
     }
     return current->len;
 }
 
+int linenoiseColumns(void)
+{
+    struct current current;
+    enableRawMode (&current);
+    getWindowSize (&current);
+    disableRawMode (&current);
+    return current.cols;
+}
+
 char *linenoise(const char *prompt)
 {
     int count;
@@ -1220,10 +1383,10 @@ char *linenoise(const char *prompt)
     char buf[LINENOISE_MAX_LINE];
 
     if (enableRawMode(&current) == -1) {
-       printf("%s", prompt);
+        printf("%s", prompt);
         fflush(stdout);
         if (fgets(buf, sizeof(buf), stdin) == NULL) {
-               return NULL;
+            return NULL;
         }
         count = strlen(buf);
         if (count && buf[count-1] == '\n') {
@@ -1239,10 +1402,14 @@ char *linenoise(const char *prompt)
         current.chars = 0;
         current.pos = 0;
         current.prompt = prompt;
+        current.capture = NULL;
+
+        count = linenoiseEdit(&current);
 
-        count = linenoisePrompt(&current);
         disableRawMode(&current);
         printf("\n");
+
+        free(current.capture);
         if (count == -1) {
             return NULL;
         }
@@ -1256,10 +1423,16 @@ int linenoiseHistoryAdd(const char *line) {
 
     if (history_max_len == 0) return 0;
     if (history == NULL) {
-        history = (char**)malloc(sizeof(char*)*history_max_len);
+        history = (char **)malloc(sizeof(char*)*history_max_len);
         if (history == NULL) return 0;
         memset(history,0,(sizeof(char*)*history_max_len));
     }
+
+    /* do not insert duplicate lines into history */
+    if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) {
+        return 0;
+    }
+
     linecopy = strdup(line);
     if (!linecopy) return 0;
     if (history_len == history_max_len) {
@@ -1272,6 +1445,10 @@ int linenoiseHistoryAdd(const char *line) {
     return 1;
 }
 
+int linenoiseHistoryGetMaxLen(void) {
+    return history_max_len;
+}
+
 int linenoiseHistorySetMaxLen(int len) {
     char **newHistory;
 
@@ -1279,10 +1456,18 @@ int linenoiseHistorySetMaxLen(int len) {
     if (history) {
         int tocopy = history_len;
 
-        newHistory = (char**)malloc(sizeof(char*)*len);
+        newHistory = (char **)malloc(sizeof(char*)*len);
         if (newHistory == NULL) return 0;
-        if (len < tocopy) tocopy = len;
-        memcpy(newHistory,history+(history_max_len-tocopy), sizeof(char*)*tocopy);
+
+        /* If we can't copy everything, free the elements we'll not use. */
+        if (len < tocopy) {
+            int j;
+
+            for (j = 0; j < tocopy-len; j++) free(history[j]);
+            tocopy = len;
+        }
+        memset(newHistory,0,sizeof(char*)*len);
+        memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy);
         free(history);
         history = newHistory;
     }
index dcf22f7..cf8f16f 100644 (file)
@@ -54,9 +54,11 @@ void linenoiseAddCompletion(linenoiseCompletions *, const char *);
 char *linenoise(const char *prompt);
 int linenoiseHistoryAdd(const char *line);
 int linenoiseHistorySetMaxLen(int len);
+int linenoiseHistoryGetMaxLen(void);
 int linenoiseHistorySave(const char *filename);
 int linenoiseHistoryLoad(const char *filename);
 void linenoiseHistoryFree(void);
 char **linenoiseHistory(int *len);
+int linenoiseColumns(void);
 
 #endif /* __LINENOISE_H */
index cc2cd5d..80e73f3 100755 (executable)
@@ -46,7 +46,7 @@ tclexts="bootstrap initjimsh glob stdlib tclcompat"
 # Note ordering
 allexts="bootstrap aio readdir glob regexp file exec clock array stdlib tclcompat"
 
-echo "/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */"
+echo "/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */"
 
 # define some core features
 for i in _GNU_SOURCE JIM_TCL_COMPAT JIM_REFERENCES JIM_ANSIC JIM_REGEXP HAVE_NO_AUTOCONF _JIMAUTOCONF_H; do
@@ -58,25 +58,38 @@ for i in $allexts; do
        echo "#define jim_ext_$i"
 done
 
-# Can we make a bootstrap jimsh work even on mingw32?
 cat <<EOF
-#if defined(__MINGW32__)
+#if defined(_MSC_VER)
+#define TCL_PLATFORM_OS "windows"
+#define TCL_PLATFORM_PLATFORM "windows"
+#define TCL_PLATFORM_PATH_SEPARATOR ";"
+#define HAVE_MKDIR_ONE_ARG
+#define HAVE_SYSTEM
+#elif defined(__MINGW32__)
 #define TCL_PLATFORM_OS "mingw"
 #define TCL_PLATFORM_PLATFORM "windows"
 #define TCL_PLATFORM_PATH_SEPARATOR ";"
 #define HAVE_MKDIR_ONE_ARG
 #define HAVE_SYSTEM
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
+#define HAVE_SYS_TIME_H
+#define HAVE_DIRENT_H
+#define HAVE_UNISTD_H
 #else
 #define TCL_PLATFORM_OS "unknown"
 #define TCL_PLATFORM_PLATFORM "unix"
 #define TCL_PLATFORM_PATH_SEPARATOR ":"
 #define HAVE_VFORK
 #define HAVE_WAITPID
+#define HAVE_ISATTY
+#define HAVE_SYS_TIME_H
+#define HAVE_DIRENT_H
+#define HAVE_UNISTD_H
 #endif
 EOF
 
+# get JIM_VERSION from auto.def
+sed -n -e 's/^\(define JIM_VERSION.*\)/#\1/p' auto.def
+
 outputsource()
 {
         sed -e '/#include.*jim/d' -e '/#include.*utf8/d' \
@@ -85,7 +98,7 @@ outputsource()
 }
 
 # Now output header files, removing references to jim header files
-for i in utf8.h jim.h jim-subcmd.h jimregexp.h ; do
+for i in jim-win32compat.h utf8.h jim.h jim-subcmd.h jimregexp.h ; do
        outputsource $i
 done
 
@@ -99,6 +112,10 @@ done
 makeloadexts $allexts
 
 # And finally the core source code
-for i in jim.c jim-subcmd.c utf8.c jim-interactive.c jim-format.c jimregexp.c jimsh.c; do
+for i in jim.c jim-subcmd.c utf8.c jim-format.c jimregexp.c jim-win32compat.c; do
        outputsource $i
 done
+echo "#ifndef JIM_BOOTSTRAP_LIB_ONLY"
+outputsource jim-interactive.c
+outputsource jimsh.c
+echo "#endif"
old mode 100644 (file)
new mode 100755 (executable)
index 8dba920..1908d00 100755 (executable)
@@ -12,16 +12,18 @@ set c 0
 
 while {[gets $f buf] >= 0} {
        if {[string match "~~*" $buf]} {
-               if {[string match "*:*" $prev]} {
+               if {[string match "*: *" $prev]} {
                        incr c
                        set target cmd_$c
                        set lines [linsert $lines end-1 "\[\[$target\]\]"]
+                       set prevlist [split $prev ":, "]
                } else {
-                       set target _$prev
+                       set target _[string map {:: _} $prev]
+                       set prevlist [list $prev]
                }
-               foreach cmd [split $prev ":,"] {
+               foreach cmd $prevlist {
                        set cmd [string trim $cmd]
-                       if {[regexp {^[a-z.]+$} $cmd]} {
+                       if {[regexp {^[a-z.:]+$} $cmd]} {
                                lappend commands [list $cmd $target]
                                set cdict($cmd) $target
                        }
@@ -66,5 +68,9 @@ lappend mapping @INSERTINDEX@ [join $index \n]
 
 # Output the result
 foreach line $lines {
-       puts [string map $mapping $line]
+       if {[string first ` $line] >= 0 || [string first @ $line] >= 0} {
+               puts [string map $mapping $line]
+       } else {
+               puts $line
+       }
 }
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/jim/make-release.sh b/jim/make-release.sh
new file mode 100755 (executable)
index 0000000..07030c7
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+version=`sed -n -e 's/.*JIM_VERSION *\([0-9]*\).*/0.\1/p' jim.h`
+
+if [ `git clean -nqx | wc -l` -ne 0 ]; then
+       git clean -nqx
+       echo "***: Tree not clean"
+       exit 1
+fi
+if [ `git status | grep modified: | wc -l` -ne 0 ]; then
+       git status
+       echo "***: Modified files exist"
+       exit 1
+fi
+mkdir jimtcl-$version
+rsync --exclude=.git --exclude=jimtcl-$version -a ./ jimtcl-$version/
+tar -czf jimtcl-$version.tar.gz jimtcl-$version
+rm -rf jimtcl-$version
+ls -l jimtcl-$version.tar.gz
diff --git a/jim/nshelper.tcl b/jim/nshelper.tcl
new file mode 100755 (executable)
index 0000000..33acb51
--- /dev/null
@@ -0,0 +1,130 @@
+# Implements script-based implementations of various namespace
+# subcommands
+#
+# (c) 2011 Steve Bennett <steveb@workware.net.au>
+#
+
+proc {namespace delete} {args} {
+       foreach name $args {
+               if {$name ni {:: ""}} {
+                       set name [uplevel 1 [list ::namespace canon $name]]
+                       foreach i [info commands ${name}::*] { rename $i "" }
+                       uplevel #0 [list unset {*}[info globals ${name}::*]]
+               }
+       }
+}
+
+proc {namespace origin} {name} {
+       set nscanon [uplevel 1 [list ::namespace canon $name]]
+       if {[exists -alias $nscanon]} {
+               tailcall {namespace origin} [info alias $nscanon]
+       }
+       if {[exists -command $nscanon]} {
+               return ::$nscanon
+       }
+       if {[exists -command $name]} {
+               return ::$name
+       }
+
+       return -code error "invalid command name \"$name\""
+}
+
+proc {namespace which} {{type -command} name} {
+       set nsname ::[uplevel 1 [list ::namespace canon $name]]
+       if {$type eq "-variable"} {
+               return $nsname
+       }
+       if {$type eq "-command"} {
+               if {[exists -command $nsname]} {
+                       return $nsname
+               } elseif {[exists -command ::$name]} {
+                       return ::$name
+               }
+               return ""
+       }
+       return -code error {wrong # args: should be "namespace which ?-command? ?-variable? name"}
+}
+
+
+proc {namespace code} {arg} {
+       if {[string first "::namespace inscope " $arg] == 0} {
+               # Already scoped
+               return $arg
+       }
+       list ::namespace inscope [uplevel 1 ::namespace current] $arg
+}
+
+proc {namespace inscope} {name arg args} {
+       tailcall namespace eval $name $arg $args
+}
+
+proc {namespace import} {args} {
+       set current [uplevel 1 ::namespace canon]
+
+       foreach pattern $args {
+               foreach cmd [info commands [namespace canon $current $pattern]] {
+                       alias ${current}::[namespace tail $cmd] $cmd
+               }
+       }
+}
+
+# namespace-aware info commands: procs, channels, globals, locals, vars
+proc {namespace info} {cmd {pattern *}} {
+       set current [uplevel 1 ::namespace canon]
+       # Now we may need to strip $pattern
+       if {[string first :: $pattern] == 0} {
+               set global 1
+               set prefix ::
+       } else {
+               set global 0
+               set clen [string length $current]
+               incr clen 2
+       }
+       set fqp [namespace canon $current $pattern]
+       switch -glob -- $cmd {
+               co* - p* {
+                       if {$global} {
+                               set result [info $cmd $fqp]
+                       } else {
+                               # Add commands in the current namespace
+                               set r {}
+                               foreach c [info $cmd $fqp] {
+                                       dict set r [string range $c $clen end] 1
+                               }
+                               if {[string match co* $cmd]} {
+                                       # Now in the global namespace
+                                       foreach c [info -nons commands $pattern] {
+                                               dict set r $c 1
+                                       }
+                               }
+                               set result [dict keys $r]
+                       }
+               }
+               ch* {
+                       set result [info channels $pattern]
+               }
+               v* {
+                       #puts "uplevel #0 info gvars $fqp"
+                       set result [uplevel #0 info -nons vars $fqp]
+               }
+               g* {
+                       set result [info globals $fqp]
+               }
+               l* {
+                       set result [uplevel 1 info -nons locals $pattern]
+               }
+       }
+       if {$global} {
+               set result [lmap p $result { set p $prefix$p }]
+       }
+       return $result
+}
+
+proc {namespace upvar} {ns args} {
+       set nscanon ::[uplevel 1 [list ::namespace canon $ns]]
+       set script [list upvar 0]
+       foreach {other local} $args {
+               lappend script ${nscanon}::$other $local
+       }
+       tailcall {*}$script
+}
diff --git a/jim/oo.tcl b/jim/oo.tcl
new file mode 100755 (executable)
index 0000000..b57daf5
--- /dev/null
@@ -0,0 +1,92 @@
+# OO support for Jim Tcl, with multiple inheritance
+
+# Create a new class $classname, with the given
+# dictionary as class variables. These are the initial
+# variables which all newly created objects of this class are
+# initialised with.
+#
+# If a list of baseclasses is given,
+# methods and instance variables are inherited.
+# The *last* baseclass can be accessed directly with [super]
+# Later baseclasses take precedence if the same method exists in more than one
+proc class {classname {baseclasses {}} classvars} {
+       set baseclassvars {}
+       foreach baseclass $baseclasses {
+               # Start by mapping all methods to the parent class
+               foreach method [$baseclass methods] { alias "$classname $method" "$baseclass $method" }
+               # Now import the base class classvars
+               set baseclassvars [dict merge $baseclassvars [$baseclass classvars]]
+               # The last baseclass will win here
+               proc "$classname baseclass" {} baseclass { return $baseclass }
+       }
+
+       # Merge in the baseclass vars with lower precedence
+       set classvars [dict merge $baseclassvars $classvars]
+       set vars [lsort [dict keys $classvars]]
+
+       # This is the class dispatcher for $classname
+       # It simply dispatches 'classname cmd' to a procedure named {classname cmd}
+       # with a nice message if the class procedure doesn't exist
+       proc $classname {{cmd new} args} classname {
+               if {![exists -command "$classname $cmd"]} {
+                       return -code error "$classname, unknown command \"$cmd\": should be [join [$classname methods] ", "]"
+               }
+               tailcall "$classname $cmd" {*}$args
+       }
+
+       # Constructor
+       proc "$classname new" {{instvars {}}} {classname classvars} {
+               set instvars [dict merge $classvars $instvars]
+
+               # This is the object dispatcher for $classname.
+               # Store the classname in both the ref value and tag, for debugging
+               # ref tag (for debugging)
+               proc [ref $classname $classname "$classname finalize"] {method args} {classname instvars} {
+                       if {![exists -command "$classname $method"]} {
+                               return -code error "$classname, unknown method \"$method\": should be [join [$classname methods] ", "]"
+                       }
+                       "$classname $method" {*}$args
+               }
+       }
+       # Finalizer to invoke destructor during garbage collection
+       proc "$classname finalize" {ref classname} { $ref destroy }
+       # Method creator
+       proc "$classname method" {method arglist body} classname {
+               proc "$classname $method" $arglist {body} {
+                       # Make sure this isn't incorrectly called without an object
+                       if {![uplevel exists instvars]} {
+                               return -code error -level 2 "\"[lindex [info level 0] 0]\" method called with no object"
+                       }
+                       set self [lindex [info level -1] 0]
+                       # Note that we can't use 'dict with' here because
+                       # the dict isn't updated until the body completes.
+                       foreach _ [$self vars] {upvar 1 instvars($_) $_}
+                       unset _
+                       eval $body
+               }
+       }
+       # Other simple class procs
+       proc "$classname vars" {} vars { return $vars }
+       proc "$classname classvars" {} classvars { return $classvars }
+       proc "$classname classname" {} classname { return $classname }
+       proc "$classname methods" {} classname {
+               lsort [lmap p [info procs "$classname *"] {
+                       lindex [split $p " "] 1
+               }]
+       }
+       # Pre-defined some instance methods
+       $classname method destroy {} { rename $self "" }
+       $classname method get {var} { set $var }
+       $classname method eval {{locals {}} code} {
+               foreach var $locals { upvar 2 $var $var }
+               eval $code
+       }
+       return $classname
+}
+
+# From within a method, invokes the given method on the base class.
+# Note that this will only call the last baseclass given
+proc super {method args} {
+       upvar self self
+       uplevel 2 [$self baseclass] $method {*}$args
+}
old mode 100644 (file)
new mode 100755 (executable)
index 4b5ec3a..348a114
@@ -9,56 +9,45 @@
 
 # Parse the unicode data from: http://unicode.org/Public/UNIDATA/UnicodeData.txt
 # to generate case mapping tables
+set map(lower) {}
+set map(upper) {}
+set map(title) {}
 
 set f [open [lindex $argv 0]]
-set extoff 0
-puts "static const struct casemap unicode_case_mapping\[\] = \{"
 while {[gets $f buf] >= 0} {
-       foreach {code name class x x x x x x x x x upper lower} [split $buf ";"] break
-       set code 0x$code
-       if {$code <= 0x7f} {
+       set title ""
+       set lower ""
+       set upper ""
+       foreach {code name class x x x x x x x x x upper lower title} [split $buf ";"] break
+       set codex [string tolower 0x$code]
+       if {$codex <= 0x7f} {
                continue
        }
-       if {$code > 0xffff} {
+       if {$codex > 0xffff} {
                break
        }
-       if {$class ne "Lu" && $class ne "Ll"} {
+       if {![string match L* $class]} {
                continue
        }
-       if {$upper eq ""} {
-               set upper $code
-       } else {
-               set upper 0x$upper
+       if {$upper ne ""} {
+               lappend map(upper) $codex [string tolower 0x$upper]
        }
-       if {$lower eq ""} {
-               set lower $code
-       } else {
-               set lower 0x$lower
+       if {$lower ne ""} {
+               lappend map(lower) $codex [string tolower 0x$lower]
        }
-       if {$upper == $code && $lower == $code} {
-               continue
-       }
-       set l [expr {$lower - $code}]
-       set u [expr {$upper - $code}]
-       if {abs($u) > 127 || abs($l) > 127} {
-               # Can't encode both in one byte, so use indirection
-               lappend jumptable $code $lower $upper
-               set l -128
-               set u $extoff
-               incr extoff
-               if {$extoff > 0xff} {
-                       error "Too many entries in the offset table!"
+       if {$title ne "" && $title ne $upper} {
+               if {$title eq $code} {
+                       set title 0
                }
+               lappend map(title) $codex [string tolower 0x$title]
        }
-       set entry [string tolower "$code, $l, $u"]
-       puts "    { $entry },"
 }
 close $f
-puts "\};\n"
 
-# Now the jump table
-puts "static const struct caseextmap unicode_extmap\[\] = \{"
-foreach {c l u} $jumptable {
-       puts "    { $l, $u },"
+foreach type {upper lower title} {
+       puts "static const struct casemap unicode_case_mapping_$type\[\] = \{"
+       foreach {code alt} $map($type) {
+               puts "\t{ $code, $alt },"
+       }
+       puts "\};\n"
 }
-puts "\};\n"
old mode 100644 (file)
new mode 100755 (executable)
index de796d9..8e25377
@@ -1,3 +1,6 @@
+# These regression tests all provoked crashes at some point.
+# Thus they are kept separate from the regular test suite in tests/
+
 # REGTEST 1
 # 27Jan2005 - SIGSEGV for bug on Jim_DuplicateObj().
 
@@ -153,6 +156,96 @@ catch {
 # Actually, the test passes if no objects leaked on exit
 puts "TEST 23 PASSED"
 
+# REGTEST 24
+# 13 Nov 2011 - invalid cached global var
+proc a {} {
+    foreach i {1 2} {
+        incr z [set ::t]
+        unset ::t
+    }
+}
+set t 6
+catch a
+puts "TEST 24 PASSED"
+
+# REGTEST 25
+# 14 Nov 2011 - link global var to proc var
+proc a {} {
+    set x 3
+    upvar 0 x ::globx
+}
+set globx 0
+catch {
+    a
+}
+incr globx
+puts "TEST 25 PASSED"
+
+# REGTEST 26
+# 2 Dec 2011 - infinite eval recursion
+catch {
+    set x 0
+    set y {incr x; eval $y}
+    eval $y
+} msg
+puts "TEST 26 PASSED"
+
+# REGTEST 27
+# 2 Dec 2011 - infinite alias recursion
+catch {
+    proc p {} {}
+    alias p p
+    p
+} msg
+puts "TEST 27 PASSED"
+
+# REGTEST 28
+# 16 Dec 2011 - ref count problem with finalizers
+catch {
+    ref x x [list dummy]
+    collect
+}
+puts "TEST 28 PASSED"
+
+# REGTEST 29
+# Reference counting problem at exit
+set x [lindex {} 0]
+info source $x
+eval $x
+puts "TEST 29 PASSED"
+
+# REGTEST 30
+# non-UTF8 string tolower 
+string tolower "/mod/video/h\303\203\302\244xan_ witchcraft through the ages_20131101_0110.t"
+puts "TEST 30 PASSED"
+
+# REGTEST 31
+# infinite lsort -unique with error
+catch {lsort -unique -real {foo 42.0}}
+puts "TEST 31 PASSED"
+
+# REGTEST 32
+# return -code eval should only used by tailcall, but this incorrect usage
+# should not crash the interpreter
+proc a {} { tailcall b }
+proc b {} { return -code eval c }
+proc c {} {}
+catch -eval a
+puts "TEST 32 PASSED"
+
+# REGTEST 33
+# unset array variable which doesn't exist
+array unset blahblah abc
+puts "TEST 33 PASSED"
+
+# REGTEST 34
+# onexception and writable conflict
+set f [open [info nameofexecutable]]
+$f onexception {incr x}
+$f writable {incr y}
+$f close
+puts "TEST 34 PASSED"
+
 # TAKE THE FOLLOWING puts AS LAST LINE
 
 puts "--- ALL TESTS PASSED ---"
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 3abeb3e..d0256d0
@@ -1,17 +1,8 @@
-# Create a single word alias (proc) for one or more words
-# e.g. alias x info exists
-# if {[x var]} ...
-proc alias {name args} {
-       set prefix $args
-       proc $name args prefix {
-               tailcall {*}$prefix {*}$args
-       }
-}
+# Implements script-based standard commands for Jim Tcl
 
 # Creates an anonymous procedure
 proc lambda {arglist args} {
-       set name [ref {} function lambda.finalizer]
-       tailcall proc $name $arglist {*}$args
+       tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args
 }
 
 proc lambda.finalizer {name val} {
@@ -20,16 +11,13 @@ proc lambda.finalizer {name val} {
 
 # Like alias, but creates and returns an anonyous procedure
 proc curry {args} {
-       set prefix $args
-       lambda args prefix {
-               tailcall {*}$prefix {*}$args
-       }
+       alias [ref {} function lambda.finalizer] {*}$args
 }
 
 # Returns the given argument.
 # Useful with 'local' as follows:
 #   proc a {} {...}
-#   local function a 
+#   local function a
 #
 #   set x [lambda ...]
 #   local function $x
@@ -38,53 +26,47 @@ proc function {value} {
        return $value
 }
 
-# Tcl 8.5 lassign
-proc lassign {list args} {
-       # in case the list is empty...
-       lappend list {}
-       uplevel 1 [list foreach $args $list break]
-       lrange $list [llength $args] end-1
-}
-
-# Returns a list of proc filename line ...
+# Returns a live stack trace as a list of proc filename line ...
 # with 3 entries for each stack frame (proc),
 # (deepest level first)
-proc stacktrace {} {
+proc stacktrace {{skip 0}} {
        set trace {}
-       foreach level [range 1 [info level]] {
-               lassign [info frame -$level] p f l
-               lappend trace $p $f $l
+       incr skip
+       foreach level [range $skip [info level]] {
+               lappend trace {*}[info frame -$level]
        }
        return $trace
 }
 
 # Returns a human-readable version of a stack trace
 proc stackdump {stacktrace} {
-       set result {}
-       set count 0
+       set lines {}
        foreach {l f p} [lreverse $stacktrace] {
-               if {$count} {
-                       append result \n
-               }
-               incr count
+               set line {}
                if {$p ne ""} {
-                       append result "in procedure '$p' "
+                       append line "in procedure '$p' "
                        if {$f ne ""} {
-                               append result "called "
+                               append line "called "
                        }
                }
                if {$f ne ""} {
-                       append result "at file \"$f\", line $l"
+                       append line "at file \"$f\", line $l"
+               }
+               if {$line ne ""} {
+                       lappend lines $line
                }
        }
-       return $result
+       join $lines \n
 }
 
 # Sort of replacement for $::errorInfo
 # Usage: errorInfo error ?stacktrace?
 proc errorInfo {msg {stacktrace ""}} {
        if {$stacktrace eq ""} {
+               # By default add the stack backtrace and the live stacktrace
                set stacktrace [info stacktrace]
+               # omit the procedure 'errorInfo' from the stack
+               lappend stacktrace {*}[stacktrace 1]
        }
        lassign $stacktrace p f l
        if {$f ne ""} {
@@ -105,7 +87,7 @@ proc {info nameofexecutable} {} {
                        return [file join [pwd] $::jim_argv0]
                }
                foreach path [split [env PATH ""] $::tcl_platform(pathSeparator)] {
-                       set exec [file join [pwd] $path $::jim_argv0]
+                       set exec [file join [pwd] [string map {\\ /} $path] $::jim_argv0]
                        if {[file executable $exec]} {
                                return $exec
                        }
@@ -115,21 +97,42 @@ proc {info nameofexecutable} {} {
 }
 
 # Script-based implementation of 'dict with'
-proc {dict with} {dictVar args script} {
-       upvar $dictVar dict
+proc {dict with} {&dictVar {args key} script} {
        set keys {}
-       foreach {n v} [dict get $dict {*}$args] {
+       foreach {n v} [dict get $dictVar {*}$key] {
                upvar $n var_$n
                set var_$n $v
                lappend keys $n
        }
        catch {uplevel 1 $script} msg opts
-       if {[info exists dict] && [dict exists $dict {*}$args]} {
+       if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {
                foreach n $keys {
                        if {[info exists var_$n]} {
-                               dict set dict {*}$args $n [set var_$n]
+                               dict set dictVar {*}$key $n [set var_$n]
                        } else {
-                               dict unset dict {*}$args $n
+                               dict unset dictVar {*}$key $n
+                       }
+               }
+       }
+       return {*}$opts $msg
+}
+
+# Script-based implementation of 'dict update'
+proc {dict update} {&varName args script} {
+       set keys {}
+       foreach {n v} $args {
+               upvar $v var_$v
+               if {[dict exists $varName $n]} {
+                       set var_$v [dict get $varName $n]
+               }
+       }
+       catch {uplevel 1 $script} msg opts
+       if {[info exists varName]} {
+               foreach {n v} $args {
+                       if {[info exists var_$v]} {
+                               dict set varName $n [set var_$v]
+                       } else {
+                               dict unset varName $n
                        }
                }
        }
@@ -148,3 +151,62 @@ proc {dict merge} {dict args} {
        }
        return $dict
 }
+
+proc {dict replace} {dictionary {args {key value}}} {
+       if {[llength ${key value}] % 2} {
+               tailcall {dict replace}
+       }
+       tailcall dict merge $dictionary ${key value}
+}
+
+# Script-based implementation of 'dict lappend'
+proc {dict lappend} {varName key {args value}} {
+       upvar $varName dict
+       if {[exists dict] && [dict exists $dict $key]} {
+               set list [dict get $dict $key]
+       }
+       lappend list {*}$value
+       dict set dict $key $list
+}
+
+# Script-based implementation of 'dict append'
+proc {dict append} {varName key {args value}} {
+       upvar $varName dict
+       if {[exists dict] && [dict exists $dict $key]} {
+               set str [dict get $dict $key]
+       }
+       append str {*}$value
+       dict set dict $key $str
+}
+
+# Script-based implementation of 'dict incr'
+proc {dict incr} {varName key {increment 1}} {
+       upvar $varName dict
+       if {[exists dict] && [dict exists $dict $key]} {
+               set value [dict get $dict $key]
+       }
+       incr value $increment
+       dict set dict $key $value
+}
+
+# Script-based implementation of 'dict remove'
+proc {dict remove} {dictionary {args key}} {
+       foreach k $key {
+               dict unset dictionary $k
+       }
+       return $dictionary
+}
+
+# Script-based implementation of 'dict values'
+proc {dict values} {dictionary {pattern *}} {
+       dict keys [lreverse $dictionary] $pattern
+}
+
+# Script-based implementation of 'dict for'
+proc {dict for} {vars dictionary script} {
+       if {[llength $vars] != 2} {
+               return -code error "must have exactly two variable names"
+       }
+       dict size $dictionary
+       tailcall foreach $vars $dictionary $script
+}
old mode 100644 (file)
new mode 100755 (executable)
index f1dcaa5..d74201c
@@ -29,7 +29,7 @@ MODIFICATIONS.
 
 GOVERNMENT USE: If you are acquiring this software on behalf of the
 U.S. government, the Government shall have only "Restricted Rights"
-in the software and related documentation as defined in the Federal 
+in the software and related documentation as defined in the Federal
 Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
 are acquiring the software on behalf of the Department of Defense, the
 software shall be classified as "Commercial Computer Software" and the
@@ -37,4 +37,4 @@ Government shall have only "Restricted Rights" as defined in Clause
 252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
 authors grant the U.S. Government and others acting in its behalf
 permission to use and distribute the software in accordance with the
-terms specified in this license. 
+terms specified in this license.
old mode 100644 (file)
new mode 100755 (executable)
index 8e5b128..2a5560c
@@ -1,12 +1,14 @@
-# (c) 2008 Steve Bennett <steveb@workware.net.au>
-#
 # Loads some Tcl-compatible features.
 # I/O commands, case, lassign, parray, errorInfo, ::tcl_platform, ::env
 # try, throw, file copy, file delete -force
+#
+# (c) 2008 Steve Bennett <steveb@workware.net.au>
+
 
 # Set up the ::env array
 set env [env]
 
+# Provide Tcl-compatible I/O commands
 if {[info commands stdout] ne ""} {
        # Tcl-compatible I/O commands
        foreach p {gets flush close eof seek tell} {
@@ -40,7 +42,7 @@ if {[info commands stdout] ne ""} {
                foreach {n v} $args {
                        switch -glob -- $n {
                                -bl* {
-                                       $f ndelay $v
+                                       $f ndelay $(!$v)
                                }
                                -bu* {
                                        $f buffering $v
@@ -56,47 +58,6 @@ if {[info commands stdout] ne ""} {
        }
 }
 
-# case var ?in? pattern action ?pattern action ...?
-proc case {var args} {
-       # Skip dummy parameter
-       if {[lindex $args 0] eq "in"} {
-               set args [lrange $args 1 end]
-       }
-
-       # Check for single arg form
-       if {[llength $args] == 1} {
-               set args [lindex $args 0]
-       }
-
-       # Check for odd number of args
-       if {[llength $args] % 2 != 0} {
-               return -code error "extra case pattern with no body"
-       }
-
-       # Internal function to match a value agains a list of patterns
-       local proc case.checker {value pattern} {
-               string match $pattern $value
-       }
-
-       foreach {value action} $args {
-               if {$value eq "default"} {
-                       set do_action $action
-                       continue
-               } elseif {[lsearch -bool -command case.checker $value $var]} {
-                       set do_action $action
-                       break
-               }
-       }
-
-       if {[info exists do_action]} {
-               set rc [catch [list uplevel 1 $do_action] result opts]
-               if {$rc} {
-                       incr opts(-level)
-               }
-               return {*}$opts $result
-       }
-}
-
 # fileevent isn't needed in Jim, but provide it for compatibility
 proc fileevent {args} {
        tailcall {*}$args
@@ -104,7 +65,7 @@ proc fileevent {args} {
 
 # Second, option argument is a glob pattern
 # Third, optional argument is a "putter" function
-# 
+#
 proc parray {arrayname {pattern *} {puts puts}} {
        upvar $arrayname a
 
@@ -130,9 +91,21 @@ proc {file copy} {{force {}} source target} {
 
                set in [open $source]
 
-               if {$force eq "" && [file exists $target]} {
-                       $in close
-                       error "error copying \"$source\" to \"$target\": file already exists"
+               if {[file exists $target]} {
+                       if {$force eq ""} {
+                               error "error copying \"$source\" to \"$target\": file already exists"
+                       }
+                       # If source and target are the same, nothing to do
+                       if {$source eq $target} {
+                               return
+                       }
+                       # Hard linked, or case-insensitive filesystem
+                       # Note: mingw returns ino=0 for every file :-(
+                       file stat $source ss
+                       file stat $target ts
+                       if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {
+                               return
+                       }
                }
                set out [open $target w]
                $in copyto $out
@@ -181,14 +154,14 @@ proc popen {cmd {mode r}} {
 }
 
 # A wrapper around 'pid' which can return the pids for 'popen'
-local proc pid {{chan {}}} {
-       if {$chan eq ""} {
+local proc pid {{channelId {}}} {
+       if {$channelId eq ""} {
                tailcall upcall pid
        }
-       if {[catch {$chan tell}]} {
-               return -code error "can not find channel named \"$chan\""
+       if {[catch {$channelId tell}]} {
+               return -code error "can not find channel named \"$channelId\""
        }
-       if {[catch {$chan pid} pids]} {
+       if {[catch {$channelId pid} pids]} {
                return ""
        }
        return $pids
diff --git a/jim/tests/Makefile b/jim/tests/Makefile
new file mode 100755 (executable)
index 0000000..452bd8d
--- /dev/null
@@ -0,0 +1,7 @@
+jimsh ?= ../jimsh
+
+test:
+       @rc=0; for i in *.test; do LD_LIBRARY_PATH=..:$(LD_LIBRARY_PATH) $(jimsh) $$i || rc=$?; done; exit $$rc
+
+clean:
+       rm -f gorp.file2 gorp.file sleepx test1 exec.tmp1
diff --git a/jim/tests/alias.test b/jim/tests/alias.test
new file mode 100755 (executable)
index 0000000..b1774fd
--- /dev/null
@@ -0,0 +1,247 @@
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+needs cmd array
+needs cmd ref
+
+test alias-1.1 "One word alias" {
+       set x 2
+       alias newincr incr
+       newincr x 
+} {3}
+
+test alias-1.4 "Two word alias" {
+       alias infoexists info exists
+       infoexists x
+} {1}
+
+test alias-1.5 "Replace alias" {
+       alias newincr infoexists
+       newincr x
+} {1}
+
+test alias-1.6 "Delete alias" {
+       rename newincr ""
+       catch {newincr x}
+} {1}
+
+test alias-1.7 "Replace alias with proc" {
+       proc infoexists {n} {
+               return yes
+       }
+       infoexists any
+} {yes}
+
+test alias-1.8 "Replace proc with alias" {
+       alias infoexists info exists
+       infoexists any
+} {0}
+
+test alias-1.9 "error message from alias" -body {
+       alias newstring string
+       newstring match
+} -returnCodes error -result {wrong # args: should be "string match ?-nocase? pattern string"}
+
+test alias-1.10 "info alias" {
+       alias x info exists
+       info alias x
+} {info exists}
+
+test alias-1.10 "info alias on non-alias" -body {
+       info alias format
+} -returnCodes error -result {command "format" is not an alias}
+
+test curry-1.1 "One word curry" {
+       set x 2
+       set one [curry incr]
+       $one x 
+} {3}
+
+test curry-1.4 "Two word curry" {
+       set two [curry info exists]
+       list [$two x] [$two y]
+} {1 0}
+
+test curry-1.5 "Delete curry" {
+       unset one two
+       collect
+} {2}
+
+test local-1.2 "local curry in proc" {
+       proc a {} {
+               local set p [curry info exists]
+               set x 1
+               list $p [$p x] [$p y]
+       }
+       lassign [a] p exists_x exists_y
+       list [info procs $p] $exists_x $exists_y
+} {{} 1 0}
+
+test local-1.2 "set local curry in proc" {
+       proc a {} {
+               set p [local curry info exists]
+               set x 1
+               list $p [$p x] [$p y]
+       }
+       lassign [a] p exists_x exists_y
+       list [info procs $p] $exists_x $exists_y
+} {{} 1 0}
+
+test local-1.3 "local alias in proc" {
+       proc a {} {
+               local alias p info exists
+               set x 1
+               list [p x] [p y]
+       }
+       lassign [a] exists_x exists_y
+       list [info commands p] $exists_x $exists_y
+} {{} 1 0}
+
+test local-1.5 "local proc in proc" {
+       set ::x 1
+       proc a {} {
+               local proc b {} { incr ::x }
+               b
+               set ::x
+       }
+       a
+       list [info procs b] $::x
+} {{} 2}
+
+test local-1.6 "local lambda in lsort" {
+       proc a {} {
+               lsort -command [local lambda {a b} {string compare $a $b}] {d a f g}
+       }
+       a
+} {a d f g}
+
+test local-1.7 "check no reference procs" {
+       info procs "<reference*"
+} {}
+
+test local-1.8 "local on non-existent command" {
+       list [catch {local set x blah} msg] $msg
+} {1 {invalid command name "blah"}}
+
+test local-1.9 "local on existing proc" {
+       proc x {} {
+               proc a {b} {incr b}
+               local function a
+               set c [lambda b {incr b -1}]
+               local function $c
+               lappend result [a 1] [$c 2]
+       }
+       set result [x]
+       list [info procs a] $result 
+} {{} {2 1}}
+
+test statics-1.1 "missing static variable init" {
+       unset -nocomplain c
+       catch {
+               proc a {b} {c} {
+                       # No initialiser for c
+               }
+       }
+} 1
+
+test statics-1.2 "static variable with invalid name" {
+       catch {
+               proc a {b} "{c\0d 4}" {
+               }
+       }
+} 1
+
+test statics-1.3 "duplicate static variable" {
+       catch {
+               proc a {b} {{c 1} {c 2}} {
+               }
+       }
+} 1
+
+test statics-1.4 "bad static variable init" {
+       catch {
+               proc a {b} {{c 1 2}} {
+               }
+       }
+} 1
+
+test local-2.1 "proc over existing proc" {
+       proc a {b} {incr b}
+       proc t {x} {
+               proc a {b} {incr b -1}
+               a $x
+       }
+       unset -nocomplain x
+       lappend x [a 5]
+       lappend x [t 5]
+       lappend x [a 5]
+} {6 4 4}
+
+test local-2.2 "local proc over existing proc" {
+       proc a {b} {incr b}
+       proc t {x} {
+               local proc a {b} {incr b -1}
+               a $x
+       }
+       unset -nocomplain x
+       lappend x [a 5]
+       lappend x [t 5]
+       lappend x [a 5]
+} {6 4 6}
+
+test local-2.3 "local proc over existing proc" {
+       proc a {b} {incr b}
+       proc t {x} {
+               local proc a {b} {incr b -1}
+               a $x
+       }
+       unset -nocomplain x
+       lappend x [a 5]
+       lappend x [t 5]
+       lappend x [a 5]
+} {6 4 6}
+
+test upcall-1.1 "upcall pushed proc" {
+       proc a {b} {incr b}
+       local proc a {b} {
+               incr b 10
+               # invoke the original defn via upcall
+               return [upcall a $b]
+       }
+       # Should call the new defn which will call the original defn
+       a 3
+} 14
+
+test upcall-1.2 "upcall in proc" {
+       proc a {b} {incr b}
+       proc t {c} {
+               local proc a {b} {
+                       incr b 10
+                       return [upcall a $b]
+               }
+               a $c
+       }
+       unset -nocomplain x
+       lappend x [t 5]
+       lappend x [a 5]
+       set x
+} {16 6}
+
+test upcall-1.3 "double upcall" {
+       proc a {} {return 1}
+       local proc a {} {list 2 {*}[upcall a]}
+       local proc a {} {list 3 {*}[upcall a]}
+       a
+} {3 2 1}
+
+test upcall-1.4 "upcall errors" {
+       proc a {} {return 1}
+       list [catch {upcall a} msg] $msg
+} {1 {no previous command: "a"}}
+
+test upcall-1.4 "upcall errors" {
+       proc a {} {upcall a}
+       list [catch a msg] $msg
+} {1 {no previous command: "a"}}
+
+testreport
diff --git a/jim/tests/apply.test b/jim/tests/apply.test
new file mode 100755 (executable)
index 0000000..abf6438
--- /dev/null
@@ -0,0 +1,136 @@
+# Commands covered:  apply
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2005-2006 Miguel Sofer
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd apply
+
+\f
+# Tests for wrong number of arguments
+
+test apply-1.1 {too few arguments} -returnCodes error -body {
+    apply
+} -result {wrong # args: should be "apply lambdaExpr ?arg ...?"}
+
+# Tests for malformed lambda
+
+test apply-2.0 {malformed lambda} -returnCodes error -body {
+    set lambda a
+    apply $lambda
+} -result {can't interpret "a" as a lambda expression}
+test apply-2.1 {malformed lambda} -returnCodes error -body {
+    set lambda [list a b c d]
+    apply $lambda
+} -result {can't interpret "a b c d" as a lambda expression}
+test apply-2.2 {malformed lambda} -body {
+    set lambda [list {{}} boo]
+    apply $lambda
+} -returnCodes error -match glob -result {*argument with no name}
+test apply-2.3 {malformed lambda} {
+    set lambda [list {{a b c}} boo]
+    list [catch {apply $lambda} msg] $msg
+} {1 {too many fields in argument specifier "a b c"}}
+
+# Note that Jim allow both of these
+test apply-2.4 {malformed lambda} tcl {
+    set lambda [list a(1) {return $a(1)}]
+    list [catch {apply $lambda x} msg] $msg
+} {1 {formal parameter "a(1)" is an array element}}
+test apply-2.5 {malformed lambda} tcl {
+    set lambda [list a::b {return $a::b}]
+    list [catch {apply $lambda x} msg] $msg
+} {1 {formal parameter "a::b" is not a simple name}}
+
+# Tests for runtime errors in the lambda expression
+
+test apply-4.1 {error in arguments to lambda expression} -body {
+    set lambda [list x {set x 1}]
+    apply $lambda
+} -returnCodes error -result {wrong # args: should be "apply lambdaExpr x"}
+test apply-4.2 {error in arguments to lambda expression} -body {
+    set lambda [list x {set x 1}]
+    apply $lambda a b
+} -returnCodes error -result {wrong # args: should be "apply lambdaExpr x"}
+
+test apply-5.1 {runtime error in lambda expression} {
+    set lambda [list {} {error foo}]
+    list [catch {apply $lambda} msg] $msg
+} {1 foo}
+
+# Tests for correct execution; as the implementation is the same as that for
+# procs, the general functionality is mostly tested elsewhere
+
+test apply-6.1 {info level} {
+    set lev [info level]
+    set lambda [list {} {info level}]
+    expr {[apply $lambda] - $lev}
+} 1
+test apply-6.2 {info level} tcl {
+    set lambda [list {} {info level 0}]
+    apply $lambda
+} {apply {{} {info level 0}}}
+test apply-6.3 {info level} tcl {
+    set lambda [list args {info level 0}]
+    apply $lambda x y
+} {apply {args {info level 0}} x y}
+
+# Tests for correct argument treatment
+
+set applyBody {
+    set res {}
+    foreach v [lsort [info locals]] {
+       if {$v eq "res"} continue
+       lappend res [list $v [set $v]]
+    }
+    set res
+}
+
+test apply-8.1 {args treatment} {
+    apply [list args $applyBody] 1 2 3
+} {{args {1 2 3}}}
+test apply-8.2 {args treatment} {
+    apply [list {x args} $applyBody] 1 2
+} {{args 2} {x 1}}
+test apply-8.3 {args treatment} {
+    apply [list {x args} $applyBody] 1 2 3
+} {{args {2 3}} {x 1}}
+test apply-8.4 {default values} {
+    apply [list {{x 1} {y 2}} $applyBody] 
+} {{x 1} {y 2}}
+test apply-8.5 {default values} {
+    apply [list {{x 1} {y 2}} $applyBody] 3 4
+} {{x 3} {y 4}}
+test apply-8.6 {default values} {
+    apply [list {{x 1} {y 2}} $applyBody] 3
+} {{x 3} {y 2}}
+test apply-8.7 {default values} {
+    apply [list {x {y 2}} $applyBody] 1
+} {{x 1} {y 2}}
+test apply-8.8 {default values} {
+    apply [list {x {y 2}} $applyBody] 1 3
+} {{x 1} {y 3}}
+test apply-8.9 {default values} {
+    apply [list {x {y 2} args} $applyBody] 1
+} {{args {}} {x 1} {y 2}}
+test apply-8.10 {default values} {
+    apply [list {x {y 2} args} $applyBody] 1 3
+} {{args {}} {x 1} {y 3}}
+
+::tcltest::cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/jim/tests/applyns.test b/jim/tests/applyns.test
new file mode 100755 (executable)
index 0000000..0483692
--- /dev/null
@@ -0,0 +1,99 @@
+# Commands covered:  apply
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2005-2006 Miguel Sofer
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd apply
+needs cmd namespace
+
+# Tests for runtime errors in the lambda expression
+
+# Note: Jim doesn't have the concept of non-existent namespaces
+
+test apply-3.1 {non-existing namespace} -constraints tcl -body {
+    apply [list x {set x 1} ::NONEXIST::FOR::SURE] x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+test apply-3.2 {non-existing namespace} -constraints tcl -body {
+    namespace eval ::NONEXIST::FOR::SURE {}
+    set lambda [list x {set x 1} ::NONEXIST::FOR::SURE]
+    apply $lambda x
+    namespace delete ::NONEXIST
+    apply $lambda x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+test apply-3.3 {non-existing namespace} -constraints tcl -body {
+    apply [list x {set x 1} NONEXIST::FOR::SURE] x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+test apply-3.4 {non-existing namespace} -constraints tcl -body {
+    namespace eval ::NONEXIST::FOR::SURE {}
+    set lambda [list x {set x 1} NONEXIST::FOR::SURE]
+    apply $lambda x
+    namespace delete ::NONEXIST
+    apply $lambda x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+
+# Tests for correct namespace scope
+
+namespace eval ::testApply {
+    proc testApply args {return testApply}
+}
+
+test apply-7.1 {namespace access} {
+    set ::testApply::x 0
+    set body {set x 1; set x}
+    list [apply [list args $body ::testApply]] $::testApply::x
+} {1 0}
+test apply-7.2 {namespace access} {
+    set ::testApply::x 0
+    set body {variable x; set x}
+    list [apply [list args $body ::testApply]] $::testApply::x
+} {0 0}
+test apply-7.3 {namespace access} {
+    set ::testApply::x 0
+    set body {variable x; set x 1}
+    list [apply [list args $body ::testApply]] $::testApply::x
+} {1 1}
+test apply-7.4 {namespace access} {
+    set ::testApply::x 0
+    set body {testApply}
+    apply [list args $body ::testApply]
+} testApply
+test apply-7.5 {namespace access} {
+    set ::testApply::x 0
+    set body {set x 1; set x}
+    list [apply [list args $body testApply]] $::testApply::x
+} {1 0}
+test apply-7.6 {namespace access} {
+    set ::testApply::x 0
+    set body {variable x; set x}
+    list [apply [list args $body testApply]] $::testApply::x
+} {0 0}
+test apply-7.7 {namespace access} {
+    set ::testApply::x 0
+    set body {variable x; set x 1}
+    list [apply [list args $body testApply]] $::testApply::x
+} {1 1}
+test apply-7.8 {namespace access} {
+    set ::testApply::x 0
+    set body {testApply}
+    apply [list args $body testApply]
+} testApply
+
+namespace delete testApply
+
+testreport
+
+# Local Variables:
+# mode: tcl
+# fill-column: 78
+# End:
diff --git a/jim/tests/array.test b/jim/tests/array.test
new file mode 100755 (executable)
index 0000000..ba88147
--- /dev/null
@@ -0,0 +1,88 @@
+source [file dirname [info script]]/testing.tcl
+
+needs cmd array
+
+unset -nocomplain a
+array set a {
+       1 one
+       2 two
+       22 "twenty two"
+       3 three
+}
+
+test array-1.1 "array exists - true" {
+       array exists a
+} {1}
+
+test array-1.2 "array exists - false" {
+       array exists b
+} {0}
+
+test array-1.3 "array size" {
+       array size a
+} {4}
+
+test array-1.4 "array size - nonexistant" {
+       array size b
+} {0}
+
+test array-1.5 "array get" {
+       set result {}
+       foreach {name value} [array get a] {
+               lappend result $name $value
+       }
+       lsort $result
+} {1 2 22 3 one three {twenty two} two}
+
+test array-1.6 "array get - pattern" {
+       set result {}
+       foreach {name value} [array get a 2*] {
+               lappend result $name $value
+       }
+       lsort $result
+} {2 22 {twenty two} two}
+
+test array-1.7 "array names" {
+       lsort [array names a]
+} {1 2 22 3}
+
+test array-1.8 "array get - pattern" {
+       lsort [array names a 2*]
+} {2 22}
+
+#set b $a
+array set b [array get a]
+
+test array-1.9 "array set - replace" {
+       array set b {22 twenty-two}
+       set b(22)
+} {twenty-two}
+
+test array-1.10 "array unset - pattern" {
+       array unset b 2*
+       lsort [array names b]
+} {1 3}
+
+test array-1.11 "array unset - all" {
+       array unset b
+       list [array size b] [array exists b]
+} {0 0}
+
+test array-1.12 "array set to invalid variable" -body {
+       unset -nocomplain a b
+       set a 1
+       array set a(1) {b c}
+} -returnCodes error -result {can't set "a(1)": variable isn't array}
+
+test array-1.13 "unset missing array element" -body {
+       unset -nocomplain a
+       set a(1) one
+       unset a(2)
+} -returnCodes error -result {can't unset "a(2)": no such element in array}
+
+test array-1.14 "access array via unset var" -body {
+       unset -nocomplain b
+       expr {$a($b) + 4}
+} -returnCodes error -result {can't read "b": no such variable}
+
+testreport
diff --git a/jim/tests/binary.test b/jim/tests/binary.test
new file mode 100755 (executable)
index 0000000..8229390
--- /dev/null
@@ -0,0 +1,2482 @@
+# This file tests the "binary" Tcl command.
+#
+# This file contains a collection of tests for one or more of the Tcl built-in
+# commands. Sourcing this file into Tcl runs the tests and generates output
+# for errors. No output means no errors were found.
+#
+# Copyright (c) 1997 by Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd binary
+testConstraint bigEndian [expr {$tcl_platform(byteOrder) eq "bigEndian"}]
+testConstraint littleEndian [expr {$tcl_platform(byteOrder) eq "littleEndian"}]
+testConstraint maxCompatibility 0
+testConstraint notImplemented 0
+
+# ----------------------------------------------------------------------
+
+test binary-0.1 {DupByteArrayInternalRep} {
+    set hdr [binary format cc 0 0316]
+    set buf hellomatt
+    set data $hdr
+    append data $buf
+    string length $data
+} 11
+
+test binary-1.1 {Tcl_BinaryObjCmd: bad args} -body {
+    binary
+} -returnCodes error -match glob -result {wrong # args: *}
+test binary-1.2 {Tcl_BinaryObjCmd: bad args} -returnCodes error -body {
+    binary foo
+} -match glob -result {*}
+test binary-1.3 {Tcl_BinaryObjCmd: format error} -returnCodes error -body {
+    binary f
+} -match glob -result {*}
+test binary-1.4 {Tcl_BinaryObjCmd: format} -body {
+    binary format ""
+} -result {}
+
+test binary-2.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format a
+} -result {not enough arguments for all format specifiers}
+test binary-2.2 {Tcl_BinaryObjCmd: format} {
+    binary format a0 foo
+} {}
+test binary-2.3 {Tcl_BinaryObjCmd: format} {
+    binary format a f
+} {f}
+test binary-2.4 {Tcl_BinaryObjCmd: format} {
+    binary format a foo
+} {f}
+test binary-2.5 {Tcl_BinaryObjCmd: format} {
+    binary format a3 foo
+} {foo}
+test binary-2.6 {Tcl_BinaryObjCmd: format} {
+    binary format a5 foo
+} foo\x00\x00
+test binary-2.7 {Tcl_BinaryObjCmd: format} {
+    binary format a*a3 foobarbaz blat
+} foobarbazbla
+test binary-2.8 {Tcl_BinaryObjCmd: format} {
+    binary format a*X3a2 foobar x
+} foox\x00r
+
+test binary-3.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format A
+} -result {not enough arguments for all format specifiers}
+test binary-3.2 {Tcl_BinaryObjCmd: format} {
+    binary format A0 f
+} {}
+test binary-3.3 {Tcl_BinaryObjCmd: format} {
+    binary format A f
+} {f}
+test binary-3.4 {Tcl_BinaryObjCmd: format} {
+    binary format A foo
+} {f}
+test binary-3.5 {Tcl_BinaryObjCmd: format} {
+    binary format A3 foo
+} {foo}
+test binary-3.6 {Tcl_BinaryObjCmd: format} {
+    binary format A5 foo
+} {foo  }
+test binary-3.7 {Tcl_BinaryObjCmd: format} {
+    binary format A*A3 foobarbaz blat
+} foobarbazbla
+test binary-3.8 {Tcl_BinaryObjCmd: format} {
+    binary format A*X3A2 foobar x
+} {foox r}
+
+test binary-4.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format B
+} -result {not enough arguments for all format specifiers}
+test binary-4.2 {Tcl_BinaryObjCmd: format} {
+    binary format B0 1
+} {}
+test binary-4.3 {Tcl_BinaryObjCmd: format} {
+    binary format B 1
+} \x80
+test binary-4.4 {Tcl_BinaryObjCmd: format} {
+    binary format B* 010011
+} \x4c
+test binary-4.5 {Tcl_BinaryObjCmd: format} {
+    binary format B8 01001101
+} \x4d
+test binary-4.6 {Tcl_BinaryObjCmd: format} {
+    binary format A2X2B9 oo 01001101
+} \x4d\x00
+test binary-4.7 {Tcl_BinaryObjCmd: format} {
+    binary format B9 010011011010
+} \x4d\x80
+test binary-4.8 {Tcl_BinaryObjCmd: format} {
+    binary format B2B3 10 010
+} \x80\x40
+test binary-4.9 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format B1B5 1 foo
+} -match glob -result {expected *}
+
+test binary-5.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format b
+} -result {not enough arguments for all format specifiers}
+test binary-5.2 {Tcl_BinaryObjCmd: format} {
+    binary format b0 1
+} {}
+test binary-5.3 {Tcl_BinaryObjCmd: format} {
+    binary format b 1
+} \x01
+test binary-5.4 {Tcl_BinaryObjCmd: format} {
+    binary format b* 010011
+} 2
+test binary-5.5 {Tcl_BinaryObjCmd: format} {
+    binary format b8 01001101
+} \xb2
+test binary-5.6 {Tcl_BinaryObjCmd: format} {
+    binary format A2X2b9 oo 01001101
+} \xb2\x00
+test binary-5.7 {Tcl_BinaryObjCmd: format} {
+    binary format b9 010011011010
+} \xb2\x01
+test binary-5.8 {Tcl_BinaryObjCmd: format} {
+    binary format b17 1
+} \x01\00\00
+test binary-5.9 {Tcl_BinaryObjCmd: format} {
+    binary format b2b3 10 010
+} \x01\x02
+test binary-5.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format b1b5 1 foo
+} -match glob -result {expected *}
+
+test binary-6.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format h
+} -result {not enough arguments for all format specifiers}
+test binary-6.2 {Tcl_BinaryObjCmd: format} {
+    binary format h0 1
+} {}
+test binary-6.3 {Tcl_BinaryObjCmd: format} {
+    binary format h 1
+} \x01
+test binary-6.4 {Tcl_BinaryObjCmd: format} {
+    binary format h c
+} \x0c
+test binary-6.5 {Tcl_BinaryObjCmd: format} {
+    binary format h* baadf00d
+} \xab\xda\x0f\xd0
+test binary-6.6 {Tcl_BinaryObjCmd: format} {
+    binary format h4 c410
+} \x4c\x01
+test binary-6.7 {Tcl_BinaryObjCmd: format} {
+    binary format h6 c4102
+} \x4c\x01\x02
+test binary-6.8 {Tcl_BinaryObjCmd: format} {
+    binary format h5 c41020304
+} \x4c\x01\x02
+test binary-6.9 {Tcl_BinaryObjCmd: format} {
+    binary format a3X3h5 foo 2
+} \x02\x00\x00
+test binary-6.10 {Tcl_BinaryObjCmd: format} {
+    binary format h2h3 23 456
+} \x32\x54\x06
+test binary-6.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format h2 foo
+} -match glob -result {expected *}
+
+test binary-7.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format H
+} -result {not enough arguments for all format specifiers}
+test binary-7.2 {Tcl_BinaryObjCmd: format} {
+    binary format H0 1
+} {}
+test binary-7.3 {Tcl_BinaryObjCmd: format} {
+    binary format H 1
+} \x10
+test binary-7.4 {Tcl_BinaryObjCmd: format} {
+    binary format H c
+} \xc0
+test binary-7.5 {Tcl_BinaryObjCmd: format} {
+    binary format H* baadf00d
+} \xba\xad\xf0\x0d
+test binary-7.6 {Tcl_BinaryObjCmd: format} {
+    binary format H4 c410
+} \xc4\x10
+test binary-7.7 {Tcl_BinaryObjCmd: format} {
+    binary format H6 c4102
+} \xc4\x10\x20
+test binary-7.8 {Tcl_BinaryObjCmd: format} {
+    binary format H5 c41023304
+} \xc4\x10\x20
+test binary-7.9 {Tcl_BinaryObjCmd: format} {
+    binary format a3X3H5 foo 2
+} \x20\x00\x00
+test binary-7.10 {Tcl_BinaryObjCmd: format} {
+    binary format H2H3 23 456
+} \x23\x45\x60
+test binary-7.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format H2 foo
+} -match glob -result {expected *}
+
+test binary-8.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format c
+} -result {not enough arguments for all format specifiers}
+test binary-8.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format c blat
+} -match glob -result {expected *}
+test binary-8.3 {Tcl_BinaryObjCmd: format} {
+    binary format c0 0x50
+} {}
+test binary-8.4 {Tcl_BinaryObjCmd: format} {
+    binary format c 0x50
+} P
+test binary-8.5 {Tcl_BinaryObjCmd: format} {
+    binary format c 0x5052
+} R
+test binary-8.6 {Tcl_BinaryObjCmd: format} {
+    binary format c2 {0x50 0x52}
+} PR
+test binary-8.7 {Tcl_BinaryObjCmd: format} {
+    binary format c2 {0x50 0x52 0x53}
+} PR
+test binary-8.8 {Tcl_BinaryObjCmd: format} {
+    binary format c* {0x50 0x52}
+} PR
+test binary-8.9 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format c2 {0x50}
+} -result {number of elements in list does not match count}
+test binary-8.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    set a {0x50 0x51}
+    binary format c $a
+} -result "expected integer but got \"0x50 0x51\""
+test binary-8.11 {Tcl_BinaryObjCmd: format} {
+    set a {0x50 0x51}
+    binary format c1 $a
+} P
+
+test binary-9.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format s
+} -result {not enough arguments for all format specifiers}
+test binary-9.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format s blat
+} -result {expected integer but got "blat"}
+test binary-9.3 {Tcl_BinaryObjCmd: format} {
+    binary format s0 0x50
+} {}
+test binary-9.4 {Tcl_BinaryObjCmd: format} {
+    binary format s 0x50
+} P\x00
+test binary-9.5 {Tcl_BinaryObjCmd: format} {
+    binary format s 0x5052
+} RP
+test binary-9.6 {Tcl_BinaryObjCmd: format} {
+    binary format s 0x505251 0x53
+} QR
+test binary-9.7 {Tcl_BinaryObjCmd: format} {
+    binary format s2 {0x50 0x52}
+} P\x00R\x00
+test binary-9.8 {Tcl_BinaryObjCmd: format} {
+    binary format s* {0x5051 0x52}
+} QPR\x00
+test binary-9.9 {Tcl_BinaryObjCmd: format} {
+    binary format s2 {0x50 0x52 0x53} 0x54
+} P\x00R\x00
+test binary-9.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format s2 {0x50}
+} -result {number of elements in list does not match count}
+test binary-9.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    set a {0x50 0x51}
+    binary format s $a
+} -result "expected integer but got \"0x50 0x51\""
+test binary-9.12 {Tcl_BinaryObjCmd: format} {
+    set a {0x50 0x51}
+    binary format s1 $a
+} P\x00
+
+test binary-10.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format S
+} -result {not enough arguments for all format specifiers}
+test binary-10.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format S blat
+} -result {expected integer but got "blat"}
+test binary-10.3 {Tcl_BinaryObjCmd: format} {
+    binary format S0 0x50
+} {}
+test binary-10.4 {Tcl_BinaryObjCmd: format} {
+    binary format S 0x50
+} \x00P
+test binary-10.5 {Tcl_BinaryObjCmd: format} {
+    binary format S 0x5052
+} PR
+test binary-10.6 {Tcl_BinaryObjCmd: format} {
+    binary format S 0x505251 0x53
+} RQ
+test binary-10.7 {Tcl_BinaryObjCmd: format} {
+    binary format S2 {0x50 0x52}
+} \x00P\x00R
+test binary-10.8 {Tcl_BinaryObjCmd: format} {
+    binary format S* {0x5051 0x52}
+} PQ\x00R
+test binary-10.9 {Tcl_BinaryObjCmd: format} {
+    binary format S2 {0x50 0x52 0x53} 0x54
+} \x00P\x00R
+test binary-10.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format S2 {0x50}
+} -result {number of elements in list does not match count}
+test binary-10.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    set a {0x50 0x51}
+    binary format S $a
+} -result "expected integer but got \"0x50 0x51\""
+test binary-10.12 {Tcl_BinaryObjCmd: format} {
+    set a {0x50 0x51}
+    binary format S1 $a
+} \x00P
+
+test binary-11.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format i
+} -result {not enough arguments for all format specifiers}
+test binary-11.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format i blat
+} -result {expected integer but got "blat"}
+test binary-11.3 {Tcl_BinaryObjCmd: format} {
+    binary format i0 0x50
+} {}
+test binary-11.4 {Tcl_BinaryObjCmd: format} {
+    binary format i 0x50
+} P\x00\x00\x00
+test binary-11.5 {Tcl_BinaryObjCmd: format} {
+    binary format i 0x5052
+} RP\x00\x00
+test binary-11.6 {Tcl_BinaryObjCmd: format} {
+    binary format i 0x505251 0x53
+} QRP\x00
+test binary-11.7 {Tcl_BinaryObjCmd: format} {
+    binary format i1 {0x505251 0x53}
+} QRP\x00
+test binary-11.8 {Tcl_BinaryObjCmd: format} {
+    binary format i 0x53525150
+} PQRS
+test binary-11.9 {Tcl_BinaryObjCmd: format} {
+    binary format i2 {0x50 0x52}
+} P\x00\x00\x00R\x00\x00\x00
+test binary-11.10 {Tcl_BinaryObjCmd: format} {
+    binary format i* {0x50515253 0x52}
+} SRQPR\x00\x00\x00
+test binary-11.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format i2 {0x50}
+} -result {number of elements in list does not match count}
+test binary-11.12 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    set a {0x50 0x51}
+    binary format i $a
+} -result "expected integer but got \"0x50 0x51\""
+test binary-11.13 {Tcl_BinaryObjCmd: format} {
+    set a {0x50 0x51}
+    binary format i1 $a
+} P\x00\x00\x00
+
+test binary-12.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format I
+} -result {not enough arguments for all format specifiers}
+test binary-12.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format I blat
+} -result {expected integer but got "blat"}
+test binary-12.3 {Tcl_BinaryObjCmd: format} {
+    binary format I0 0x50
+} {}
+test binary-12.4 {Tcl_BinaryObjCmd: format} {
+    binary format I 0x50
+} \x00\x00\x00P
+test binary-12.5 {Tcl_BinaryObjCmd: format} {
+    binary format I 0x5052
+} \x00\x00PR
+test binary-12.6 {Tcl_BinaryObjCmd: format} {
+    binary format I 0x505251 0x53
+} \x00PRQ
+test binary-12.7 {Tcl_BinaryObjCmd: format} {
+    binary format I1 {0x505251 0x53}
+} \x00PRQ
+test binary-12.8 {Tcl_BinaryObjCmd: format} {
+    binary format I 0x53525150
+} SRQP
+test binary-12.9 {Tcl_BinaryObjCmd: format} {
+    binary format I2 {0x50 0x52}
+} \x00\x00\x00P\x00\x00\x00R
+test binary-12.10 {Tcl_BinaryObjCmd: format} {
+    binary format I* {0x50515253 0x52}
+} PQRS\x00\x00\x00R
+test binary-12.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format i2 {0x50}
+} -result {number of elements in list does not match count}
+test binary-12.12 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    set a {0x50 0x51}
+    binary format I $a
+} -result "expected integer but got \"0x50 0x51\""
+test binary-12.13 {Tcl_BinaryObjCmd: format} {
+    set a {0x50 0x51}
+    binary format I1 $a
+} \x00\x00\x00P
+
+test binary-13.1 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format f} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-13.2 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format f blat} msg] $msg
+} {1 {expected number but got "blat"}}
+test binary-13.3 {Tcl_BinaryObjCmd: format} {
+    binary format f0 1.6
+} {}
+test binary-13.4 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format f 1.6
+} \x3f\xcc\xcc\xcd
+test binary-13.5 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format f 1.6
+} \xcd\xcc\xcc\x3f
+test binary-13.6 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format f* {1.6 3.4}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-13.7 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format f* {1.6 3.4}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-13.8 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format f2 {1.6 3.4}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-13.9 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format f2 {1.6 3.4}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-13.10 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format f2 {1.6 3.4 5.6}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-13.11 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format f2 {1.6 3.4 5.6}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-13.12 {Tcl_BinaryObjCmd: float overflow} {bigEndian maxCompatibility} {
+    binary format f -3.402825e+38
+} \xff\x7f\xff\xff
+test binary-13.13 {Tcl_BinaryObjCmd: float overflow} {littleEndian maxCompatibility} {
+    binary format f -3.402825e+38
+} \xff\xff\x7f\xff
+test binary-13.14 {Tcl_BinaryObjCmd: float underflow} bigEndian {
+    binary format f -3.402825e-100
+} \x80\x00\x00\x00
+test binary-13.15 {Tcl_BinaryObjCmd: float underflow} littleEndian {
+    binary format f -3.402825e-100
+} \x00\x00\x00\x80
+test binary-13.16 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format f2 {1.6}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-13.17 {Tcl_BinaryObjCmd: format} {
+    set a {1.6 3.4}
+    list [catch {binary format f $a} msg] $msg
+} [list 1 "expected number but got \"1.6 3.4\""]
+test binary-13.18 {Tcl_BinaryObjCmd: format} bigEndian {
+    set a {1.6 3.4}
+    binary format f1 $a
+} \x3f\xcc\xcc\xcd
+test binary-13.19 {Tcl_BinaryObjCmd: format} littleEndian {
+    set a {1.6 3.4}
+    binary format f1 $a
+} \xcd\xcc\xcc\x3f
+
+test binary-14.1 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format d} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-14.2 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format d blat} msg] $msg
+} {1 {expected number but got "blat"}}
+test binary-14.3 {Tcl_BinaryObjCmd: format} {
+    binary format d0 1.6
+} {}
+test binary-14.4 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format d 1.6
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a
+test binary-14.5 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format d 1.6
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f
+test binary-14.6 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format d* {1.6 3.4}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-14.7 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format d* {1.6 3.4}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-14.8 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format d2 {1.6 3.4}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-14.9 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format d2 {1.6 3.4}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-14.10 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format d2 {1.6 3.4 5.6}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-14.11 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format d2 {1.6 3.4 5.6}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-14.14 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format d2 {1.6}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-14.15 {Tcl_BinaryObjCmd: format} {
+    set a {1.6 3.4}
+    list [catch {binary format d $a} msg] $msg
+} [list 1 "expected number but got \"1.6 3.4\""]
+test binary-14.16 {Tcl_BinaryObjCmd: format} bigEndian {
+    set a {1.6 3.4}
+    binary format d1 $a
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a
+test binary-14.17 {Tcl_BinaryObjCmd: format} littleEndian {
+    set a {1.6 3.4}
+    binary format d1 $a
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f
+test binary-14.18 {FormatNumber: Bug 1116542} {
+    binary scan [binary format d 1.25] d w
+    set w
+} 1.25
+
+test binary-15.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format ax*a "y" "z"
+} -result {cannot use "*" in format string with "x"}
+test binary-15.2 {Tcl_BinaryObjCmd: format} {
+    binary format axa "y" "z"
+} y\x00z
+test binary-15.3 {Tcl_BinaryObjCmd: format} {
+    binary format ax3a "y" "z"
+} y\x00\x00\x00z
+test binary-15.4 {Tcl_BinaryObjCmd: format} {
+    binary format a*X3x3a* "foo" "z"
+} \x00\x00\x00z
+test binary-15.5 {Tcl_BinaryObjCmd: format - bug #1923966} {
+    binary format x0s 1
+} \x01\x00
+test binary-15.6 {Tcl_BinaryObjCmd: format - bug #1923966} {
+    binary format x0ss 1 1
+} \x01\x00\x01\x00
+test binary-15.7 {Tcl_BinaryObjCmd: format - bug #1923966} {
+    binary format x1s 1
+} \x00\x01\x00
+test binary-15.8 {Tcl_BinaryObjCmd: format - bug #1923966} {
+    binary format x1ss 1 1
+} \x00\x01\x00\x01\x00
+
+test binary-16.1 {Tcl_BinaryObjCmd: format} {
+    binary format a*X*a "foo" "z"
+} zoo
+test binary-16.2 {Tcl_BinaryObjCmd: format} {
+    binary format aX3a "y" "z"
+} z
+test binary-16.3 {Tcl_BinaryObjCmd: format} {
+    binary format a*Xa* "foo" "zy"
+} fozy
+test binary-16.4 {Tcl_BinaryObjCmd: format} {
+    binary format a*X3a "foobar" "z"
+} foozar
+test binary-16.5 {Tcl_BinaryObjCmd: format} {
+    binary format a*X3aX2a "foobar" "z" "b"
+} fobzar
+
+test binary-17.1 {Tcl_BinaryObjCmd: format} {
+    binary format @1
+} \x00
+test binary-17.2 {Tcl_BinaryObjCmd: format} {
+    binary format @5a2 "ab"
+} \x00\x00\x00\x00\x00\x61\x62
+test binary-17.3 {Tcl_BinaryObjCmd: format} {
+    binary format {a*  @0  a2 @* a*} "foobar" "ab" "blat"
+} abobarblat
+
+test binary-18.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format u0a3 abc abd
+} -result {bad field specifier "u"}
+
+test binary-19.1 {Tcl_BinaryObjCmd: errors} -returnCodes error -body {
+    binary s
+} -match glob -result {*}
+test binary-19.2 {Tcl_BinaryObjCmd: errors} -returnCodes error -body {
+    binary scan foo
+} -result {wrong # args: should be "binary scan value formatString ?varName ...?"}
+test binary-19.3 {Tcl_BinaryObjCmd: scan} {
+    binary scan {} {}
+} 0
+
+test binary-20.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc a
+} -result {not enough arguments for all format specifiers}
+test binary-20.2 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan abc a arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-20.3 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    set arg1 abc
+    list [binary scan abc a0 arg1] $arg1
+} -result {1 {}}
+test binary-20.4 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc a* arg1] $arg1
+} -result {1 abc}
+test binary-20.5 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc a5 arg1] [info exists arg1]
+} -result {0 0}
+test binary-20.6 {Tcl_BinaryObjCmd: scan} {
+    set arg1 foo
+    list [binary scan abc a2 arg1] $arg1
+} {1 ab}
+test binary-20.7 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+} -body {
+    list [binary scan abcdef a2a2 arg1 arg2] $arg1 $arg2
+} -result {2 ab cd}
+test binary-20.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc a2 arg1(a)] $arg1(a)
+} -result {1 ab}
+test binary-20.9 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc a arg1(a)] $arg1(a)
+} -result {1 a}
+
+# As soon as a conversion runs out of bytes, scan should stop
+test binary-20.10 {Tcl_BinaryObjCmd: scan, too few bytes} -setup {
+    unset -nocomplain arg1 arg2
+} -body {
+    list [binary scan abc a5a2 arg1 arg2] [info exists arg1] [info exists arg2]
+} -result {0 0 0}
+
+test binary-21.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc A
+} -result {not enough arguments for all format specifiers}
+test binary-21.2 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan abc A arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-21.3 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    set arg1 abc
+    list [binary scan abc A0 arg1] $arg1
+} -result {1 {}}
+test binary-21.4 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc A* arg1] $arg1
+} -result {1 abc}
+test binary-21.5 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc A5 arg1] [info exists arg1]
+} -result {0 0}
+test binary-21.6 {Tcl_BinaryObjCmd: scan} {
+    set arg1 foo
+    list [binary scan abc A2 arg1] $arg1
+} {1 ab}
+test binary-21.7 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+} -body {
+    list [binary scan abcdef A2A2 arg1 arg2] $arg1 $arg2
+} -result {2 ab cd}
+test binary-21.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc A2 arg1(a)] $arg1(a)
+} -result {1 ab}
+test binary-21.9 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc A2 arg1(a)] $arg1(a)
+} -result {1 ab}
+test binary-21.10 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan abc A arg1(a)] $arg1(a)
+} -result {1 a}
+test binary-21.11 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan "abc def \x00  " A* arg1] $arg1
+} -result {1 {abc def}}
+test binary-21.12 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -body {
+    list [binary scan "abc def \x00ghi  " A* arg1] $arg1
+} -result [list 1 "abc def \x00ghi"]
+
+test binary-22.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc b
+} -result {not enough arguments for all format specifiers}
+test binary-22.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 b* arg1] $arg1
+} {1 0100101011001010}
+test binary-22.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x82\x53 b arg1] $arg1
+} {1 0}
+test binary-22.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x82\x53 b1 arg1] $arg1
+} {1 0}
+test binary-22.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x82\x53 b0 arg1] $arg1
+} {1 {}}
+test binary-22.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 b5 arg1] $arg1
+} {1 01001}
+test binary-22.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 b8 arg1] $arg1
+} {1 01001010}
+test binary-22.8 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 b14 arg1] $arg1
+} {1 01001010110010}
+test binary-22.9 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 b14 arg1] $arg1
+} {0 foo}
+test binary-22.10 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 b1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-22.11 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1 arg2
+} -body {
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x07\x87\x05 b5b* arg1 arg2] $arg1 $arg2
+} -result {2 11100 1110000110100000}
+
+# As soon as a conversion runs out of bytes, scan should stop
+test binary-20.12 {Tcl_BinaryObjCmd: scan, too few bytes} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52 b14b8 arg1 arg2] $arg1 $arg2
+} {0 foo bar}
+
+test binary-23.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc B
+} -result {not enough arguments for all format specifiers}
+test binary-23.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 B* arg1] $arg1
+} {1 0101001001010011}
+test binary-23.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x82\x53 B arg1] $arg1
+} {1 1}
+test binary-23.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x82\x53 B1 arg1] $arg1
+} {1 1}
+test binary-23.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 B0 arg1] $arg1
+} {1 {}}
+test binary-23.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 B5 arg1] $arg1
+} {1 01010}
+test binary-23.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 B8 arg1] $arg1
+} {1 01010010}
+test binary-23.8 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 B14 arg1] $arg1
+} {1 01010010010100}
+test binary-23.9 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 B14 arg1] $arg1
+} {0 foo}
+test binary-23.10 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 B1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-23.11 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1 arg2
+} -body {
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x70\x87\x05 B5B* arg1 arg2] $arg1 $arg2
+} -result {2 01110 1000011100000101}
+
+test binary-24.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc h
+} -result {not enough arguments for all format specifiers}
+test binary-24.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 h* arg1] $arg1
+} {1 253a}
+test binary-24.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \xc2\xa3 h arg1] $arg1
+} {1 2}
+test binary-24.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x82\x53 h1 arg1] $arg1
+} {1 2}
+test binary-24.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 h0 arg1] $arg1
+} {1 {}}
+test binary-24.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \xf2\x53 h2 arg1] $arg1
+} {1 2f}
+test binary-24.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 h3 arg1] $arg1
+} {1 253}
+test binary-24.8 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 h3 arg1] $arg1
+} {0 foo}
+test binary-24.9 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 h1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-24.10 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1 arg2
+} -body {
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x70\x87\x05 h2h* arg1 arg2] $arg1 $arg2
+} -result {2 07 7850}
+
+test binary-25.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc H
+} -result {not enough arguments for all format specifiers}
+test binary-25.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 H* arg1] $arg1
+} {1 52a3}
+test binary-25.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \xc2\xa3 H arg1] $arg1
+} {1 c}
+test binary-25.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x82\x53 H1 arg1] $arg1
+} {1 8}
+test binary-25.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 H0 arg1] $arg1
+} {1 {}}
+test binary-25.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \xf2\x53 H2 arg1] $arg1
+} {1 f2}
+test binary-25.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\x53 H3 arg1] $arg1
+} {1 525}
+test binary-25.8 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 H3 arg1] $arg1
+} {0 foo}
+test binary-25.9 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 H1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-25.10 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x70\x87\x05 H2H* arg1 arg2] $arg1 $arg2
+} {2 70 8705}
+
+test binary-26.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc c
+} -result {not enough arguments for all format specifiers}
+test binary-26.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 c* arg1] $arg1
+} {1 {82 -93}}
+test binary-26.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 c arg1] $arg1
+} {1 82}
+test binary-26.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 c1 arg1] $arg1
+} {1 82}
+test binary-26.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 c0 arg1] $arg1
+} {1 {}}
+test binary-26.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 c2 arg1] $arg1
+} {1 {82 -93}}
+test binary-26.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \xff c arg1] $arg1
+} {1 -1}
+test binary-26.8 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 c3 arg1] $arg1
+} {0 foo}
+test binary-26.9 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 c1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-26.10 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x70\x87\x05 c2c* arg1 arg2] $arg1 $arg2
+} {2 {112 -121} 5}
+test binary-26.11 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 cu* arg1] $arg1
+} {1 {82 163}}
+test binary-26.12 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 cu arg1] $arg1
+} {1 82}
+test binary-26.13 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \xff cu arg1] $arg1
+} {1 255}
+test binary-26.14 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x80\x80 cuc arg1 arg2] $arg1 $arg2
+} {2 128 -128}
+test binary-26.15 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x80\x80 ccu arg1 arg2] $arg1 $arg2
+} {2 -128 128}
+
+test binary-27.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc s
+} -result {not enough arguments for all format specifiers}
+test binary-27.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 s* arg1] $arg1
+} {1 {-23726 21587}}
+test binary-27.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 s arg1] $arg1
+} {1 -23726}
+test binary-27.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 s1 arg1] $arg1
+} {1 -23726}
+test binary-27.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 s0 arg1] $arg1
+} {1 {}}
+test binary-27.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 s2 arg1] $arg1
+} {1 {-23726 21587}}
+test binary-27.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 s1 arg1] $arg1
+} {0 foo}
+test binary-27.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 s1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-27.9 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x05 s2c* arg1 arg2] $arg1 $arg2
+} {2 {-23726 21587} 5}
+test binary-27.10 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 su* arg1] $arg1
+} {1 {41810 21587}}
+test binary-27.11 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \xff\xff\xff\xff sus arg1 arg2] $arg1 $arg2
+} {2 65535 -1}
+test binary-27.12 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \xff\xff\xff\xff ssu arg1 arg2] $arg1 $arg2
+} {2 -1 65535}
+
+test binary-28.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc S
+} -result {not enough arguments for all format specifiers}
+test binary-28.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 S* arg1] $arg1
+} {1 {21155 21332}}
+test binary-28.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 S arg1] $arg1
+} {1 21155}
+test binary-28.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 S1 arg1] $arg1
+} {1 21155}
+test binary-28.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 S0 arg1] $arg1
+} {1 {}}
+test binary-28.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 S2 arg1] $arg1
+} {1 {21155 21332}}
+test binary-28.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 S1 arg1] $arg1
+} {0 foo}
+test binary-28.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 S1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-28.9 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x05 S2c* arg1 arg2] $arg1 $arg2
+} {2 {21155 21332} 5}
+test binary-28.10 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 Su* arg1] $arg1
+} {1 {21155 21332}}
+test binary-28.11 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \xa3\x52\x54\x53 Su* arg1] $arg1
+} {1 {41810 21587}}
+
+test binary-29.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc i
+} -result {not enough arguments for all format specifiers}
+test binary-29.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i* arg1] $arg1
+} {1 {1414767442 67305985}}
+test binary-29.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i arg1] $arg1
+} {1 1414767442}
+test binary-29.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 i1 arg1] $arg1
+} {1 1414767442}
+test binary-29.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53 i0 arg1] $arg1
+} {1 {}}
+test binary-29.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i2 arg1] $arg1
+} {1 {1414767442 67305985}}
+test binary-29.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 i1 arg1] $arg1
+} {0 foo}
+test binary-29.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53\x53\x54 i1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-29.9 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 i2c* arg1 arg2] $arg1 $arg2
+} {2 {1414767442 67305985} 5}
+test binary-29.10 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iui arg1 arg2] $arg1 $arg2
+} {2 4294967295 -1}
+test binary-29.11 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iiu arg1 arg2] $arg1 $arg2
+} {2 -1 4294967295}
+test binary-29.12 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    list [binary scan \x80\x00\x00\x00\x00\x00\x00\x80 iuiu arg1 arg2] $arg1 $arg2
+} {2 128 2147483648}
+
+test binary-30.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc I
+} -result {not enough arguments for all format specifiers}
+test binary-30.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I* arg1] $arg1
+} {1 {1386435412 16909060}}
+test binary-30.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I arg1] $arg1
+} {1 1386435412}
+test binary-30.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 I1 arg1] $arg1
+} {1 1386435412}
+test binary-30.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53 I0 arg1] $arg1
+} {1 {}}
+test binary-30.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I2 arg1] $arg1
+} {1 {1386435412 16909060}}
+test binary-30.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 I1 arg1] $arg1
+} {0 foo}
+test binary-30.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53\x53\x54 I1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-30.9 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 I2c* arg1 arg2] $arg1 $arg2
+} {2 {1386435412 16909060} 5}
+test binary-30.10 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IuI arg1 arg2] $arg1 $arg2
+} {2 4294967295 -1}
+test binary-30.11 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IIu arg1 arg2] $arg1 $arg2
+} {2 -1 4294967295}
+test binary-30.12 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1 arg2
+    list [binary scan \x80\x00\x00\x00\x00\x00\x00\x80 IuIu arg1 arg2] $arg1 $arg2
+} {2 2147483648 128}
+
+test binary-31.1 {Tcl_BinaryObjCmd: scan} {
+    list [catch {binary scan abc f} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+# NB: format %.12g in Jim_DoubleToString
+# tests fixed: 31.2/3, 31.4/5, 31.6/7, 31.10/11, 31.14/15, 41.5/6, 59.2-7, 59.11-15
+test binary-31.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f* arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-31.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f* arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-31.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f arg1] $arg1
+} {1 1.60000002384}
+test binary-31.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f arg1] $arg1
+} {1 1.60000002384}
+test binary-31.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd f1 arg1] $arg1
+} {1 1.60000002384}
+test binary-31.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f f1 arg1] $arg1
+} {1 1.60000002384}
+test binary-31.8 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd f0 arg1] $arg1
+} {1 {}}
+test binary-31.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f f0 arg1] $arg1
+} {1 {}}
+test binary-31.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f2 arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-31.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f2 arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-31.12 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 foo
+    list [binary scan \x52 f1 arg1] $arg1
+} {0 foo}
+test binary-31.13 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 1
+    list [catch {binary scan \x3f\xcc\xcc\xcd f1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-31.14 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 f2c* arg1 arg2] $arg1 $arg2
+} {2 {1.60000002384 3.40000009537} 5}
+test binary-31.15 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 f2c* arg1 arg2] $arg1 $arg2
+} {2 {1.60000002384 3.40000009537} 5}
+
+test binary-32.1 {Tcl_BinaryObjCmd: scan} {
+    list [catch {binary scan abc d} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-32.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d* arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-32.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d* arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-32.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d arg1] $arg1
+} {1 1.6}
+test binary-32.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d arg1] $arg1
+} {1 1.6}
+test binary-32.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1] $arg1
+} {1 1.6}
+test binary-32.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d1 arg1] $arg1
+} {1 1.6}
+test binary-32.8 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d0 arg1] $arg1
+} {1 {}}
+test binary-32.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d0 arg1] $arg1
+} {1 {}}
+test binary-32.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d2 arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-32.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d2 arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-32.12 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 foo
+    list [binary scan \x52 d1 arg1] $arg1
+} {0 foo}
+test binary-32.13 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 1
+    list [catch {binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-32.14 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 d2c* arg1 arg2] $arg1 $arg2
+} {2 {1.6 3.4} 5}
+test binary-32.15 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40\x05 d2c* arg1 arg2] $arg1 $arg2
+} {2 {1.6 3.4} 5}
+
+test binary-33.1 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    list [binary scan abcdefg a2xa3 arg1 arg2] $arg1 $arg2
+} {2 ab def}
+test binary-33.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    set arg2 foo
+    list [binary scan abcdefg a3x*a3 arg1 arg2] $arg1 $arg2
+} {1 abc foo}
+test binary-33.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    set arg2 foo
+    list [binary scan abcdefg a3x20a3 arg1 arg2] $arg1 $arg2
+} {1 abc foo}
+test binary-33.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    set arg2 foo
+    list [binary scan abc a3x20a3 arg1 arg2] $arg1 $arg2
+} {1 abc foo}
+test binary-33.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x1a1 arg1] $arg1
+} {1 b}
+test binary-33.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x5a1 arg1] $arg1
+} {1 f}
+test binary-33.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x0a1 arg1] $arg1
+} {1 a}
+
+test binary-34.1 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    list [binary scan abcdefg a2Xa3 arg1 arg2] $arg1 $arg2
+} {2 ab bcd}
+test binary-34.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    set arg2 foo
+    list [binary scan abcdefg a3X*a3 arg1 arg2] $arg1 $arg2
+} {2 abc abc}
+test binary-34.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    set arg2 foo
+    list [binary scan abcdefg a3X20a3 arg1 arg2] $arg1 $arg2
+} {2 abc abc}
+test binary-34.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abc X20a3 arg1] $arg1
+} {1 abc}
+test binary-34.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x*X1a1 arg1] $arg1
+} {1 f}
+test binary-34.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x*X5a1 arg1] $arg1
+} {1 b}
+test binary-34.7 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x3X0a1 arg1] $arg1
+} {1 d}
+
+test binary-35.1 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+} -returnCodes error -body {
+    binary scan abcdefg a2@a3 arg1 arg2
+} -result {missing count for "@" field specifier}
+test binary-35.2 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    set arg2 foo
+    list [binary scan abcdefg a3@*a3 arg1 arg2] $arg1 $arg2
+} {1 abc foo}
+test binary-35.3 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    unset -nocomplain arg2
+    set arg2 foo
+    list [binary scan abcdefg a3@20a3 arg1 arg2] $arg1 $arg2
+} {1 abc foo}
+test binary-35.4 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef @2a3 arg1] $arg1
+} {1 cde}
+test binary-35.5 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x*@1a1 arg1] $arg1
+} {1 b}
+test binary-35.6 {Tcl_BinaryObjCmd: scan} {
+    unset -nocomplain arg1
+    list [binary scan abcdef x*@0a1 arg1] $arg1
+} {1 a}
+
+test binary-36.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abcdef u0a3
+} -result {bad field specifier "u"}
+
+
+# GetFormatSpec is pretty thoroughly tested above, but there are a few cases
+# we should text explicitly
+
+test binary-37.1 {GetFormatSpec: whitespace} {
+    binary format "a3 a5     a3" foo barblat baz
+} foobarblbaz
+test binary-37.2 {GetFormatSpec: whitespace} {
+    binary format "      " foo
+} {}
+test binary-37.3 {GetFormatSpec: whitespace} {
+    binary format "     a3" foo
+} foo
+test binary-37.4 {GetFormatSpec: whitespace} {
+    binary format "" foo
+} {}
+test binary-37.5 {GetFormatSpec: whitespace} {
+    binary format "" foo
+} {}
+test binary-37.6 {GetFormatSpec: whitespace} {
+    binary format "     a3   " foo
+} foo
+test binary-37.7 {GetFormatSpec: numbers} {
+    list [catch {binary scan abcdef "x-1" foo} msg] $msg
+} {1 {bad field specifier "-"}}
+test binary-37.8 {GetFormatSpec: numbers} {
+    catch {unset arg1}
+    set arg1 foo
+    list [binary scan abcdef "a0x3" arg1] $arg1
+} {1 {}}
+test binary-37.9 {GetFormatSpec: numbers} {
+    # test format of neg numbers
+    # bug report/fix provided by Harald Kirsch
+    set x [binary format f* {1 -1 2 -2 0}]
+    binary scan $x f* bla
+    set bla
+} {1.0 -1.0 2.0 -2.0 0.0}
+
+test binary-38.1 {FormatNumber: word alignment} {
+    set x [binary format c1s1 1 1]
+} \x01\x01\x00
+test binary-38.2 {FormatNumber: word alignment} {
+    set x [binary format c1S1 1 1]
+} \x01\x00\x01
+test binary-38.3 {FormatNumber: word alignment} {
+    set x [binary format c1i1 1 1]
+} \x01\x01\x00\x00\x00
+test binary-38.4 {FormatNumber: word alignment} {
+    set x [binary format c1I1 1 1]
+} \x01\x00\x00\x00\x01
+test binary-38.5 {FormatNumber: word alignment} bigEndian {
+    set x [binary format c1d1 1 1.6]
+} \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a
+test binary-38.6 {FormatNumber: word alignment} littleEndian {
+    set x [binary format c1d1 1 1.6]
+} \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f
+test binary-38.7 {FormatNumber: word alignment} bigEndian {
+    set x [binary format c1f1 1 1.6]
+} \x01\x3f\xcc\xcc\xcd
+test binary-38.8 {FormatNumber: word alignment} littleEndian {
+    set x [binary format c1f1 1 1.6]
+} \x01\xcd\xcc\xcc\x3f
+
+test binary-39.1 {ScanNumber: sign extension} {
+    catch {unset arg1}
+    list [binary scan \x52\xa3 c2 arg1] $arg1
+} {1 {82 -93}}
+test binary-39.2 {ScanNumber: sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 s4 arg1] $arg1
+} {1 {513 -32511 386 -32127}}
+test binary-39.3 {ScanNumber: sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 S4 arg1] $arg1
+} {1 {258 385 -32255 -32382}}
+test binary-39.4 {ScanNumber: sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 i5 arg1] $arg1
+} {1 {33620225 16843137 16876033 25297153 -2130640639}}
+test binary-39.5 {ScanNumber: sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 I5 arg1] $arg1
+} {1 {16843010 -2130640639 25297153 16876033 16843137}}
+test binary-39.6 {ScanNumber: no sign extension} {
+    catch {unset arg1}
+    list [binary scan \x52\xa3 cu2 arg1] $arg1
+} {1 {82 163}}
+test binary-39.7 {ScanNumber: no sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 su4 arg1] $arg1
+} {1 {513 33025 386 33409}}
+test binary-39.8 {ScanNumber: no sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 Su4 arg1] $arg1
+} {1 {258 385 33281 33154}}
+test binary-39.9 {ScanNumber: no sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 iu5 arg1] $arg1
+} {1 {33620225 16843137 16876033 25297153 2164326657}}
+test binary-39.10 {ScanNumber: no sign extension} {
+    catch {unset arg1}
+    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 Iu5 arg1] $arg1
+} {1 {16843010 2164326657 25297153 16876033 16843137}}
+
+test binary-40.3 {ScanNumber: NaN} -constraints {maxCompatibility} \
+    -body {
+       catch {unset arg1}
+       list [binary scan \xff\xff\xff\xff f1 arg1] $arg1
+    } \
+    -match glob \
+    -result {1 -NaN*}
+
+test binary-40.4 {ScanNumber: NaN} -constraints {maxCompatibility} \
+    -body {
+       catch {unset arg1}
+       list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d arg1] $arg1
+    } \
+    -match glob \
+    -result {1 -NaN*}
+
+test binary-41.1 {ScanNumber: word alignment} {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\x01\x00 c1s1 arg1 arg2] $arg1 $arg2
+} {2 1 1}
+test binary-41.2 {ScanNumber: word alignment} {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\x00\x01 c1S1 arg1 arg2] $arg1 $arg2
+} {2 1 1}
+test binary-41.3 {ScanNumber: word alignment} {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\x01\x00\x00\x00 c1i1 arg1 arg2] $arg1 $arg2
+} {2 1 1}
+test binary-41.4 {ScanNumber: word alignment} {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\x00\x00\x00\x01 c1I1 arg1 arg2] $arg1 $arg2
+} {2 1 1}
+test binary-41.5 {ScanNumber: word alignment} bigEndian {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\x3f\xcc\xcc\xcd c1f1 arg1 arg2] $arg1 $arg2
+} {2 1 1.60000002384}
+test binary-41.6 {ScanNumber: word alignment} littleEndian {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\xcd\xcc\xcc\x3f c1f1 arg1 arg2] $arg1 $arg2
+} {2 1 1.60000002384}
+test binary-41.7 {ScanNumber: word alignment} bigEndian {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a c1d1 arg1 arg2] $arg1 $arg2
+} {2 1 1.6}
+test binary-41.8 {ScanNumber: word alignment} littleEndian {
+    catch {unset arg1; unset arg2}
+    list [binary scan \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f c1d1 arg1 arg2] $arg1 $arg2
+} {2 1 1.6}
+
+# Test changed in Jim's fashion
+test binary-42.1 {Tcl_BinaryObjCmd: bad arguments} -returnCodes error -body {
+    binary ?
+} -match glob -result {*}
+
+# Wide int (guaranteed at least 64-bit) handling
+test binary-43.1 {Tcl_BinaryObjCmd: format wide int} {} {
+    binary format w 7810179016327718216
+} HelloTcl
+test binary-43.2 {Tcl_BinaryObjCmd: format wide int} {} {
+    binary format W 7810179016327718216
+} lcTolleH
+
+test binary-44.1 {Tcl_BinaryObjCmd: scan wide int} {} {
+    binary scan HelloTcl W x
+    set x
+} 5216694956358656876
+test binary-44.2 {Tcl_BinaryObjCmd: scan wide int} {} {
+    binary scan lcTolleH w x
+    set x
+} 5216694956358656876
+# Changed 44.3, 44.4 as Jim doesn't have 'wide' function
+test binary-44.3 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} {} {
+    binary scan [binary format w [expr {int(3) << 31}]] w x
+    set x
+} 6442450944
+test binary-44.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} {} {
+    binary scan [binary format W [expr {int(3) << 31}]] W x
+    set x
+} 6442450944
+test binary-43.5 {Tcl_BinaryObjCmd: scan wide int} {} {
+    catch {unset arg1}
+    list [binary scan \x80[string repeat \x00 7] W arg1] $arg1
+} {1 -9223372036854775808}
+# Tests binary-43.6-9 excluded as they transcend Jim's integer range.
+test binary-43.6 {Tcl_BinaryObjCmd: scan unsigned wide int} {notImplemented} {
+    catch {unset arg1}
+    list [binary scan \x80[string repeat \x00 7] Wu arg1] $arg1
+} {1 9223372036854775808}
+test binary-43.7 {Tcl_BinaryObjCmd: scan unsigned wide int} {notImplemented} {
+    catch {unset arg1}
+    list [binary scan [string repeat \x00 7]\x80 wu arg1] $arg1
+} {1 9223372036854775808}
+test binary-43.8 {Tcl_BinaryObjCmd: scan unsigned wide int} {notImplemented} {
+    catch {unset arg1 arg2}
+    list [binary scan \x80[string repeat \x00 7]\x80[string repeat \x00 7] WuW arg1 arg2] $arg1 $arg2
+} {2 9223372036854775808 -9223372036854775808}
+test binary-43.9 {Tcl_BinaryObjCmd: scan unsigned wide int} {notImplemented} {
+    catch {unset arg1 arg2}
+    list [binary scan [string repeat \x00 7]\x80[string repeat \x00 7]\x80 wuw arg1 arg2] $arg1 $arg2
+} {2 9223372036854775808 -9223372036854775808}
+
+test binary-45.1 {Tcl_BinaryObjCmd: combined wide int handling} {
+    binary scan [binary format sws 16450 -1 19521] c* x
+    set x
+} {66 64 -1 -1 -1 -1 -1 -1 -1 -1 65 76}
+test binary-45.2 {Tcl_BinaryObjCmd: combined wide int handling} {
+    binary scan [binary format sWs 16450 0x7fffffff 19521] c* x
+    set x
+} {66 64 0 0 0 0 127 -1 -1 -1 65 76}
+
+# NB: tests binary-46.* fail as Jim Tcl doesn't truncate Unicode chars to ISO-8859-1.
+
+test binary-47.1 {Tcl_BinaryObjCmd: number cache reference count handling} {
+    # This test is only reliable when memory debugging is turned on,
+    # but without even memory debugging it should still generate the
+    # expected answers and might therefore still pick up memory corruption
+    # caused by [Bug 851747].
+    list [binary scan aba ccc x x x] $x
+} {3 97}
+
+
+### TIP#129: endian specifiers ----
+
+# format t
+test binary-48.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format t
+} -result {not enough arguments for all format specifiers}
+test binary-48.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format t blat
+} -result {expected integer but got "blat"}
+test binary-48.3 {Tcl_BinaryObjCmd: format} {
+    binary format S0 0x50
+} {}
+test binary-48.4 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format t 0x50
+} \x00P
+test binary-48.5 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format t 0x50
+} P\x00
+test binary-48.6 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format t 0x5052
+} PR
+test binary-48.7 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format t 0x5052
+} RP
+test binary-48.8 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format t 0x505251 0x53
+} RQ
+test binary-48.9 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format t 0x505251 0x53
+} QR
+test binary-48.10 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format t2 {0x50 0x52}
+} \x00P\x00R
+test binary-48.11 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format t2 {0x50 0x52}
+} P\x00R\x00
+test binary-48.12 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format t* {0x5051 0x52}
+} PQ\x00R
+test binary-48.13 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format t* {0x5051 0x52}
+} QPR\x00
+test binary-48.14 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format t2 {0x50 0x52 0x53} 0x54
+} \x00P\x00R
+test binary-48.15 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format t2 {0x50 0x52 0x53} 0x54
+} P\x00R\x00
+test binary-48.16 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format t2 {0x50}
+} -result {number of elements in list does not match count}
+test binary-48.17 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    set a {0x50 0x51}
+    binary format t $a
+} -result "expected integer but got \"0x50 0x51\""
+test binary-48.18 {Tcl_BinaryObjCmd: format} bigEndian {
+    set a {0x50 0x51}
+    binary format t1 $a
+} \x00P
+test binary-48.19 {Tcl_BinaryObjCmd: format} littleEndian {
+    set a {0x50 0x51}
+    binary format t1 $a
+} P\x00
+
+# format n
+test binary-49.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format n
+} -result {not enough arguments for all format specifiers}
+test binary-49.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format n blat
+} -result {expected integer but got "blat"}
+test binary-49.3 {Tcl_BinaryObjCmd: format} {
+    binary format n0 0x50
+} {}
+test binary-49.4 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format n 0x50
+} P\x00\x00\x00
+test binary-49.5 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format n 0x5052
+} RP\x00\x00
+test binary-49.6 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format n 0x505251 0x53
+} QRP\x00
+test binary-49.7 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format i1 {0x505251 0x53}
+} QRP\x00
+test binary-49.8 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format n 0x53525150
+} PQRS
+test binary-49.9 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format n2 {0x50 0x52}
+} P\x00\x00\x00R\x00\x00\x00
+test binary-49.10 {Tcl_BinaryObjCmd: format} littleEndian {
+    binary format n* {0x50515253 0x52}
+} SRQPR\x00\x00\x00
+test binary-49.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    binary format n2 {0x50}
+} -result {number of elements in list does not match count}
+test binary-49.12 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
+    set a {0x50 0x51}
+    binary format n $a
+} -result "expected integer but got \"0x50 0x51\""
+test binary-49.13 {Tcl_BinaryObjCmd: format} littleEndian {
+    set a {0x50 0x51}
+    binary format n1 $a
+} P\x00\x00\x00
+test binary-49.14 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format n 0x50
+} \x00\x00\x00P
+test binary-49.15 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format n 0x5052
+} \x00\x00PR
+test binary-49.16 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format n 0x505251 0x53
+} \x00PRQ
+test binary-49.17 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format i1 {0x505251 0x53}
+} QRP\x00
+test binary-49.18 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format n 0x53525150
+} SRQP
+test binary-49.19 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format n2 {0x50 0x52}
+} \x00\x00\x00P\x00\x00\x00R
+test binary-49.20 {Tcl_BinaryObjCmd: format} bigEndian {
+    binary format n* {0x50515253 0x52}
+} PQRS\x00\x00\x00R
+
+# format m
+test binary-50.1 {Tcl_BinaryObjCmd: format wide int} littleEndian {
+    binary format m 7810179016327718216
+} HelloTcl
+test binary-50.2 {Tcl_BinaryObjCmd: format wide int} bigEndian {
+    binary format m 7810179016327718216
+} lcTolleH
+
+# Changed 50.3, 50.4 as Jim doesn't have 'wide' function
+test binary-50.3 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} littleEndian {
+    binary scan [binary format m [expr {int(3) << 31}]] w x
+    set x
+} 6442450944
+test binary-50.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} bigEndian {
+    binary scan [binary format m [expr {int(3) << 31}]] W x
+    set x
+} 6442450944
+
+
+# format Q/q
+test binary-51.1 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format Q} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-51.2 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format q blat} msg] $msg
+} {1 {expected number but got "blat"}}
+test binary-51.3 {Tcl_BinaryObjCmd: format} {
+    binary format q0 1.6
+} {}
+test binary-51.4 {Tcl_BinaryObjCmd: format} {} {
+    binary format Q 1.6
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a
+test binary-51.5 {Tcl_BinaryObjCmd: format} {} {
+    binary format q 1.6
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f
+test binary-51.6 {Tcl_BinaryObjCmd: format} {} {
+    binary format Q* {1.6 3.4}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-51.7 {Tcl_BinaryObjCmd: format} {} {
+    binary format q* {1.6 3.4}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-51.8 {Tcl_BinaryObjCmd: format} {} {
+    binary format Q2 {1.6 3.4}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-51.9 {Tcl_BinaryObjCmd: format} {} {
+    binary format q2 {1.6 3.4}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-51.10 {Tcl_BinaryObjCmd: format} {} {
+    binary format Q2 {1.6 3.4 5.6}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-51.11 {Tcl_BinaryObjCmd: format} {} {
+    binary format q2 {1.6 3.4 5.6}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-51.14 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format q2 {1.6}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-51.15 {Tcl_BinaryObjCmd: format} {
+    set a {1.6 3.4}
+    list [catch {binary format q $a} msg] $msg
+} [list 1 "expected number but got \"1.6 3.4\""]
+test binary-51.16 {Tcl_BinaryObjCmd: format} {} {
+    set a {1.6 3.4}
+    binary format Q1 $a
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a
+test binary-51.17 {Tcl_BinaryObjCmd: format} {} {
+    set a {1.6 3.4}
+    binary format q1 $a
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f
+
+# format R/r
+test binary-53.1 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format r} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-53.2 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format r blat} msg] $msg
+} {1 {expected number but got "blat"}}
+test binary-53.3 {Tcl_BinaryObjCmd: format} {
+    binary format f0 1.6
+} {}
+test binary-53.4 {Tcl_BinaryObjCmd: format} {} {
+    binary format R 1.6
+} \x3f\xcc\xcc\xcd
+test binary-53.5 {Tcl_BinaryObjCmd: format} {} {
+    binary format r 1.6
+} \xcd\xcc\xcc\x3f
+test binary-53.6 {Tcl_BinaryObjCmd: format} {} {
+    binary format R* {1.6 3.4}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-53.7 {Tcl_BinaryObjCmd: format} {} {
+    binary format r* {1.6 3.4}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-53.8 {Tcl_BinaryObjCmd: format} {} {
+    binary format R2 {1.6 3.4}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-53.9 {Tcl_BinaryObjCmd: format} {} {
+    binary format r2 {1.6 3.4}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-53.10 {Tcl_BinaryObjCmd: format} {} {
+    binary format R2 {1.6 3.4 5.6}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-53.11 {Tcl_BinaryObjCmd: format} {} {
+    binary format r2 {1.6 3.4 5.6}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-53.12 {Tcl_BinaryObjCmd: float overflow} {maxCompatibility} {
+    binary format R -3.402825e+38
+} \xff\x7f\xff\xff
+test binary-53.13 {Tcl_BinaryObjCmd: float overflow} {maxCompatibility} {
+    binary format r -3.402825e+38
+} \xff\xff\x7f\xff
+test binary-53.14 {Tcl_BinaryObjCmd: float underflow} {} {
+    binary format R -3.402825e-100
+} \x80\x00\x00\x00
+test binary-53.15 {Tcl_BinaryObjCmd: float underflow} {} {
+    binary format r -3.402825e-100
+} \x00\x00\x00\x80
+test binary-53.16 {Tcl_BinaryObjCmd: format} {
+    list [catch {binary format r2 {1.6}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-53.17 {Tcl_BinaryObjCmd: format} {
+    set a {1.6 3.4}
+    list [catch {binary format r $a} msg] $msg
+} [list 1 "expected number but got \"1.6 3.4\""]
+test binary-53.18 {Tcl_BinaryObjCmd: format} {} {
+    set a {1.6 3.4}
+    binary format R1 $a
+} \x3f\xcc\xcc\xcd
+test binary-53.19 {Tcl_BinaryObjCmd: format} {} {
+    set a {1.6 3.4}
+    binary format r1 $a
+} \xcd\xcc\xcc\x3f
+
+# scan t (s)
+test binary-54.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc t
+} -result {not enough arguments for all format specifiers}
+test binary-54.2 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1
+} {1 {-23726 21587}}
+test binary-54.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 t arg1] $arg1
+} {1 -23726}
+test binary-54.4 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 t1 arg1] $arg1
+} {1 -23726}
+test binary-54.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 t0 arg1] $arg1
+} {1 {}}
+test binary-54.6 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1
+} {1 {-23726 21587}}
+test binary-54.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 t1 arg1] $arg1
+} {0 foo}
+test binary-54.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 t1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-54.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
+} {2 {-23726 21587} 5}
+test binary-54.10 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x00\x80\x00\x80 tut arg1 arg2] $arg1 $arg2
+} {2 32768 -32768}
+test binary-54.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x00\x80\x00\x80 ttu arg1 arg2] $arg1 $arg2
+} {2 -32768 32768}
+
+# scan t (b)
+test binary-55.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc t
+} -result {not enough arguments for all format specifiers}
+test binary-55.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1
+} {1 {21155 21332}}
+test binary-55.3 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 t arg1] $arg1
+} {1 21155}
+test binary-55.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 t1 arg1] $arg1
+} {1 21155}
+test binary-55.5 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3 t0 arg1] $arg1
+} {1 {}}
+test binary-55.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1
+} {1 {21155 21332}}
+test binary-55.7 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 t1 arg1] $arg1
+} {0 foo}
+test binary-55.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53 t1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-55.9 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
+} {2 {21155 21332} 5}
+test binary-55.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x80\x00\x80\x00 tut arg1 arg2] $arg1 $arg2
+} {2 32768 -32768}
+test binary-55.11 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x80\x00\x80\x00 ttu arg1 arg2] $arg1 $arg2
+} {2 -32768 32768}
+
+# scan n (s)
+test binary-56.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc n
+} -result {not enough arguments for all format specifiers}
+test binary-56.2 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
+} {1 {1414767442 67305985}}
+test binary-56.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
+} {1 1414767442}
+test binary-56.4 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1
+} {1 1414767442}
+test binary-56.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53 n0 arg1] $arg1
+} {1 {}}
+test binary-56.6 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
+} {1 {1414767442 67305985}}
+test binary-56.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 n1 arg1] $arg1
+} {0 foo}
+test binary-56.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53\x53\x54 n1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-56.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
+} {2 {1414767442 67305985} 5}
+test binary-56.10 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x80\x00\x00\x00\x80\x00\x00\x00 nun arg1 arg2] $arg1 $arg2
+} {2 128 128}
+test binary-56.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x00\x00\x00\x80\x00\x00\x00\x80 nun arg1 arg2] $arg1 $arg2
+} {2 2147483648 -2147483648}
+
+# scan n (b)
+test binary-57.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
+    binary scan abc n
+} -result {not enough arguments for all format specifiers}
+test binary-57.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
+} {1 {1386435412 16909060}}
+test binary-57.3 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
+} {1 1386435412}
+test binary-57.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1
+} {1 1386435412}
+test binary-57.5 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53 n0 arg1] $arg1
+} {1 {}}
+test binary-57.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
+} {1 {1386435412 16909060}}
+test binary-57.7 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1
+    set arg1 foo
+    list [binary scan \x52 n1 arg1] $arg1
+} {0 foo}
+test binary-57.8 {Tcl_BinaryObjCmd: scan} -setup {
+    unset -nocomplain arg1
+} -returnCodes error -body {
+    set arg1 1
+    binary scan \x52\x53\x53\x54 n1 arg1(a)
+} -result {can't set "arg1(a)": variable isn't array}
+test binary-57.9 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
+} {2 {1386435412 16909060} 5}
+test binary-57.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x80\x00\x00\x00\x80\x00\x00\x00 nun arg1 arg2] $arg1 $arg2
+} {2 2147483648 -2147483648}
+test binary-57.11 {Tcl_BinaryObjCmd: scan} bigEndian {
+    unset -nocomplain arg1 arg2
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x00\x00\x00\x80\x00\x00\x00\x80 nun arg1 arg2] $arg1 $arg2
+} {2 128 128}
+
+# scan Q/q
+test binary-58.1 {Tcl_BinaryObjCmd: scan} {
+    list [catch {binary scan abc q} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-58.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q* arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q* arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q arg1] $arg1
+} {1 1.6}
+test binary-58.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q arg1] $arg1
+} {1 1.6}
+test binary-58.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q1 arg1] $arg1
+} {1 1.6}
+test binary-58.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q1 arg1] $arg1
+} {1 1.6}
+test binary-58.8 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q0 arg1] $arg1
+} {1 {}}
+test binary-58.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q0 arg1] $arg1
+} {1 {}}
+test binary-58.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q2 arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q2 arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.12 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 foo
+    list [binary scan \x52 q1 arg1] $arg1
+} {0 foo}
+test binary-58.13 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 1
+    list [catch {binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a q1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-58.14 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 Q2c* arg1 arg2] $arg1 $arg2
+} {2 {1.6 3.4} 5}
+test binary-58.15 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40\x05 q2c* arg1 arg2] $arg1 $arg2
+} {2 {1.6 3.4} 5}
+
+# scan R/r
+test binary-59.1 {Tcl_BinaryObjCmd: scan} {
+    list [catch {binary scan abc r} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-59.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R* arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-59.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r* arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-59.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R arg1] $arg1
+} {1 1.60000002384}
+test binary-59.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r arg1] $arg1
+} {1 1.60000002384}
+test binary-59.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd R1 arg1] $arg1
+} {1 1.60000002384}
+test binary-59.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f r1 arg1] $arg1
+} {1 1.60000002384}
+test binary-59.8 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd R0 arg1] $arg1
+} {1 {}}
+test binary-59.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f r0 arg1] $arg1
+} {1 {}}
+test binary-59.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1}
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R2 arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-59.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1}
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r2 arg1] $arg1
+} {1 {1.60000002384 3.40000009537}}
+test binary-59.12 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 foo
+    list [binary scan \x52 r1 arg1] $arg1
+} {0 foo}
+test binary-59.13 {Tcl_BinaryObjCmd: scan} {
+    catch {unset arg1}
+    set arg1 1
+    list [catch {binary scan \x3f\xcc\xcc\xcd r1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-59.14 {Tcl_BinaryObjCmd: scan} bigEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 R2c* arg1 arg2] $arg1 $arg2
+} {2 {1.60000002384 3.40000009537} 5}
+test binary-59.15 {Tcl_BinaryObjCmd: scan} littleEndian {
+    catch {unset arg1 arg2}
+    set arg1 foo
+    set arg2 bar
+    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 r2c* arg1 arg2] $arg1 $arg2
+} {2 {1.60000002384 3.40000009537} 5}
+
+test binary-60.1 {[binary format] with NaN} -body {
+    binary scan [binary format dqQfrR NaN NaN NaN NaN NaN NaN] dqQfrR \
+       v1 v2 v3 v4 v5 v6
+    list $v1 $v2 $v3 $v4 $v5 $v6
+} -match regexp -result {NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))?}
+
+# scan m
+test binary-61.1 {Tcl_BinaryObjCmd: scan wide int} bigEndian {
+    binary scan HelloTcl m x
+    set x
+} 5216694956358656876
+test binary-61.2 {Tcl_BinaryObjCmd: scan wide int} littleEndian {
+    binary scan lcTolleH m x
+    set x
+} 5216694956358656876
+test binary-61.3 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} littleEndian {
+    binary scan [binary format w [expr {3 << 31}]] m x
+    set x
+} 6442450944
+test binary-61.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} bigEndian {
+    binary scan [binary format W [expr {3 << 31}]] m x
+    set x
+} 6442450944
+
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+    array set ieeeValues {}
+    binary scan [binary format dd -1.0 1.0] c* c
+    switch -exact -- $c {
+       {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+           # little endian
+           binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+               ieeeValues(-Infinity)
+           binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+               ieeeValues(-Normal)
+           binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+               ieeeValues(-Subnormal)
+           binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+               ieeeValues(-0)
+           binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(+0)
+           binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+               ieeeValues(+Subnormal)
+           binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+               ieeeValues(+Normal)
+           binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+               ieeeValues(+Infinity)
+           binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+               ieeeValues(NaN)
+           set ieeeValues(littleEndian) 1
+           return 1
+       }
+       {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+           binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(-Infinity)
+           binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(-Normal)
+           binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(-Subnormal)
+           binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(-0)
+           binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(+0)
+           binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(+Subnormal)
+           binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(+Normal)
+           binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(+Infinity)
+           binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+               ieeeValues(NaN)
+           set ieeeValues(littleEndian) 0
+           return 1
+       }
+       default {
+           return 0
+       }
+    }
+}
+
+testConstraint ieeeFloatingPoint [testIEEE]
+
+# scan/format infinities
+
+test binary-62.1 {infinity} ieeeFloatingPoint {
+    binary scan [binary format q Infinity] w w
+    format 0x%016lx $w
+} 0x7ff0000000000000
+test binary-62.2 {infinity} ieeeFloatingPoint {
+    binary scan [binary format q -Infinity] w w
+    format 0x%016lx $w
+} 0xfff0000000000000
+test binary-62.3 {infinity} ieeeFloatingPoint {
+    binary scan [binary format q Inf] w w
+    format 0x%016lx $w
+} 0x7ff0000000000000
+test binary-62.4 {infinity} ieeeFloatingPoint {
+    binary scan [binary format q -Infinity] w w
+    format 0x%016lx $w
+} 0xfff0000000000000
+test binary-62.5 {infinity} ieeeFloatingPoint {
+    binary scan [binary format w 0x7ff0000000000000] q d
+    set d
+} Inf
+test binary-62.6 {infinity} ieeeFloatingPoint {
+    binary scan [binary format w 0xfff0000000000000] q d
+    set d
+} -Inf
+
+# scan/format Not-a-Number
+
+test binary-63.1 {NaN} {ieeeFloatingPoint maxCompatibility} {
+    binary scan [binary format q NaN] w w
+    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0x7ff0000000000000
+# Tests binary-63.2-4, 63.5-9, 64.2 excluded.
+# Apparently strtod (and Jim) don't have
+# advanced NaN-handling facility as Tcl does :)
+test binary-63.2 {NaN} {ieeeFloatingPoint notImplemented} {
+    binary scan [binary format q -NaN] w w
+    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0xfff0000000000000
+test binary-63.3 {NaN} {ieeeFloatingPoint notImplemented} {
+    binary scan [binary format q NaN(3123456789aBc)] w w
+    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0x7ff3123456789abc
+test binary-63.4 {NaN} {ieeeFloatingPoint notImplemented} {
+    binary scan [binary format q {NaN( 3123456789aBc)}] w w
+    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0x7ff3123456789abc
+
+# Make sure TclParseNumber() rejects invalid nan-hex formats [Bug 3402540]
+test binary-63.5 {NaN} -constraints {ieeeFloatingPoint} -body {
+    binary format q Nan(
+} -returnCodes error -match glob -result {expected number*}
+test binary-63.6 {NaN} -constraints {ieeeFloatingPoint notImplemented} -body {
+    binary format q Nan()
+} -returnCodes error -match glob -result {expected floating-point number*}
+test binary-63.7 {NaN} -constraints {ieeeFloatingPoint notImplemented} -body {
+    binary format q Nan(g)
+} -returnCodes error -match glob -result {expected floating-point number*}
+test binary-63.8 {NaN} -constraints {ieeeFloatingPoint notImplemented} -body {
+    binary format q Nan(1,2)
+} -returnCodes error -match glob -result {expected floating-point number*}
+test binary-63.9 {NaN} -constraints {ieeeFloatingPoint notImplemented} -body {
+    binary format q Nan(1234567890abcd)
+} -returnCodes error -match glob -result {expected floating-point number*}
+
+test binary-64.1 {NaN} \
+    -constraints ieeeFloatingPoint \
+    -body {
+       binary scan [binary format w 0x7ff8000000000000] q d
+       set d
+    } \
+    -match glob -result NaN*
+test binary-64.2 {NaN} \
+    -constraints {ieeeFloatingPoint notImplemented} \
+    -body {
+       binary scan [binary format w 0x7ff0123456789aBc] q d
+       set d
+    } \
+    -match glob -result NaN(*123456789abc)
+
+# NB: the problem of %.12g format in Jim_DoubleToString
+# make these tests meaningless. Excluded 65.1/3/5,7-9.
+
+test binary-65.1 {largest significand} {ieeeFloatingPoint maxCompatibility} {
+    binary scan [binary format w 0x3fcfffffffffffff] q d
+    set d
+} 0.24999999999999997
+test binary-65.2 {smallest significand} ieeeFloatingPoint {
+    binary scan [binary format w 0x3fd0000000000000] q d
+    set d
+} 0.25
+test binary-65.3 {largest significand} {ieeeFloatingPoint maxCompatibility} {
+    binary scan [binary format w 0x3fdfffffffffffff] q d
+    set d
+} 0.49999999999999994
+test binary-65.4 {smallest significand} ieeeFloatingPoint {
+    binary scan [binary format w 0x3fe0000000000000] q d
+    set d
+} 0.5
+test binary-65.5 {largest significand} {ieeeFloatingPoint maxCompatibility} {
+    binary scan [binary format w 0x3fffffffffffffff] q d
+    set d
+} 1.9999999999999998
+test binary-65.6 {smallest significand} ieeeFloatingPoint {
+    binary scan [binary format w 0x4000000000000000] q d
+    set d
+} 2.0
+test binary-65.7 {smallest significand} {ieeeFloatingPoint maxCompatibility} {
+    binary scan [binary format w 0x434fffffffffffff] q d
+    set d
+} 18014398509481982.0
+test binary-65.8 {largest significand} {ieeeFloatingPoint maxCompatibility} {
+    binary scan [binary format w 0x4350000000000000] q d
+    set d
+} 18014398509481984.0
+test binary-65.9 {largest significand} {ieeeFloatingPoint maxCompatibility} {
+    binary scan [binary format w 0x4350000000000001] q d
+    set d
+} 18014398509481988.0
+
+# Jim-specific test.
+# binary scan must return immediately if there's not enough bytes left.
+test binary-66.1 {binary scan: not enought bytes} {} {
+    unset -nocomplain arg1 arg2
+    binary scan ab is arg1 arg2
+} 0
+
+# cleanup
+::tcltest::cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/jim/tests/break.tcl b/jim/tests/break.tcl
new file mode 100755 (executable)
index 0000000..bf3fdcd
--- /dev/null
@@ -0,0 +1 @@
+break
diff --git a/jim/tests/concat.test b/jim/tests/concat.test
new file mode 100755 (executable)
index 0000000..79aec87
--- /dev/null
@@ -0,0 +1,66 @@
+source [file dirname [info script]]/testing.tcl
+
+test concat-1.1 {simple concatenation} {
+    concat a b c d e f g
+} {a b c d e f g}
+test concat-1.2 {merging lists together} {
+    concat a {b c d} {e f g h}
+} {a b c d e f g h}
+test concat-1.3 {merge lists, retain sub-lists} {
+    concat a {b {c d}} {{e f}} g h
+} {a b {c d} {e f} g h}
+test concat-1.4 {special characters} {
+    concat a\{ {b \{c d} \{d
+} "a{ b \\{c d {d"
+
+test concat-2.1 {error check: one empty argument} {
+    concat {}
+} {}
+
+test concat-3.1 {error check: no arguments} {
+    list [catch concat msg] $msg
+} {0 {}}
+
+test concat-4.1 {pruning off extra white space} {
+    concat {} {a b c}
+} {a b c}
+test concat-4.2 {pruning off extra white space} {
+    concat x y "  a b c        \n\t  " "   "  " def "
+} {x y a b c def}
+test concat-4.3 {pruning off extra white space sets length correctly} {
+    llength [concat { {{a}} }]
+} 1
+
+test concat-5.1 {Tcl_ScanCountedElement procedure - don't leave unmatched braces} {
+    # This test checks for a very tricky feature.  Any list element
+    # generated with Tcl_ScanCountedElement and Tcl_ConvertElement must
+    # have the property that it can be enclosing in curly braces to make
+    # an embedded sub-list.  If this property doesn't hold, then
+    # Tcl_DStringStartSublist doesn't work.
+
+    set x {}
+    lappend x " \\\{ \\"
+    concat $x [llength "{$x}"]
+} {\ \\\{\ \\ 1}
+
+test concat-6.1 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b\ } c
+} {a b\  c}
+test concat-6.2 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b\   } c
+} {a b\  c}
+test concat-6.3 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b\\   } c
+} {a b\\  c}
+test concat-6.4 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b } c
+} {a b c}
+test concat-6.5 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a { } c
+} {a c}
+test concat-6.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} {
+    # Check for Bug #227512.  If this violates C isspace, then it returns \xc3.
+    concat \xe0
+} \xe0
+
+testreport
diff --git a/jim/tests/dict.test b/jim/tests/dict.test
new file mode 100755 (executable)
index 0000000..c0528e8
--- /dev/null
@@ -0,0 +1,252 @@
+source [file dirname [info script]]/testing.tcl
+
+test dict-1.1 "Basic dict" {
+       set d [dict create]
+       dict set d fruit apple
+       dict set d car holden
+       #puts "d=$d"
+       #puts "d(fruit)=$d(fruit)"
+       dict get $d car
+} {holden}
+
+catch {unset d}
+
+test dict-2.1 "Dict via reference" references {
+       set d [dict create]
+       dict set d fruit apple
+       dict set d car holden
+
+       # now create a dictionary reference
+       set dref [ref $d dict]
+       dict get [getref $dref] car
+} {holden}
+
+test dict-2.2 "Modify dict via reference" references {
+       # Get the value out of the refernence
+       set d [getref $dref]
+       # Modify it
+       dict set d car toyota
+       # And put the new value back
+       setref $dref $d
+       # Finally check it
+       dict get [getref $dref] car
+} {toyota}
+
+test dict-2.3 "Modify dict via reference - one line" references {
+       # Get the value out of the refernence
+       set d [getref $dref]
+       setref $dref [dict set d car toyota]
+       # Finally check it
+       dict get [getref $dref] car
+} {toyota}
+
+# Sort a dictionary in key order - return a list
+proc dictsort {dict} {
+       set result {}
+       foreach k [lsort [dict keys $dict]] {
+               lappend result $k [dict get $dict $k]
+       }
+       return $result
+}
+
+set a [dict create a 1 b 2]
+set b [dict create b 3 c 4]
+test dict-3.1 {Merge} {
+       dict merge
+} {}
+test dict-3.2 {Merge} {
+       dictsort [dict merge $a]
+} {a 1 b 2}
+test dict-3.3 {Merge} {
+       dictsort [dict merge $b]
+} {b 3 c 4}
+test dict-3.4 {Merge} {
+       dictsort [dict merge $a $b]
+} {a 1 b 3 c 4}
+test dict-3.5 {Merge} {
+       dictsort [dict merge $b $a]
+} {a 1 b 2 c 4}
+test dict-3.6 {Merge} {
+       dictsort [dict merge $b $a {a 5}]
+} {a 5 b 2 c 4}
+test dict-3.7 {Merge} {
+       dictsort [dict merge {a 5} $b $a]
+} {a 1 b 2 c 4}
+test dict-3.8 {Merge} {
+       catch {dict merge 1 $b $a}
+} 1
+test dict-3.9 {Merge} {
+       catch {dict merge $b 1 $a}
+} 1
+test dict-3.10 {Merge} {
+       catch {dict merge $b $a 1}
+} 1
+test dict-3.11 {Merge} {
+       catch {dict merge 1}
+} 1
+
+test dict-4.1 {Dict size} {
+       dict size {a b}
+} 1
+test dict-4.2 {Dict size} {
+       dict size {a b c d}
+} 2
+
+test dict-5.1 {Dict with} {
+       proc a {} {
+               set x [dict create a b c d]
+               dict with x {
+                       set a B
+                       unset c
+               }
+               set x
+       }
+       dictsort [a]
+} {a B}
+test dict-5.2 {Dict with} {
+       proc a {} {
+               set x [dict create a b c d]
+               dict with x {
+                       set a B
+                       unset c
+               }
+               set x
+       }
+       dictsort [a]
+} {a B}
+
+test dict-22.1 {dict with command} {
+    list [catch {dict with} msg] $msg
+} {1 {wrong # args: should be "dict with dictVar ?key ...? script"}}
+test dict-22.2 {dict with command} {
+    list [catch {dict with v} msg] $msg
+} {1 {wrong # args: should be "dict with dictVar ?key ...? script"}}
+test dict-22.3 {dict with command} {
+    unset -nocomplain v
+    list [catch {dict with v {error "in body"}} msg] $msg
+} {1 {can't read "v": no such variable}}
+test dict-22.4 {dict with command} {
+    set a {b c d e}
+    unset -nocomplain b d
+    set result [list [info exist b] [info exist d]]
+    dict with a {
+       lappend result [info exist b] [info exist d] $b $d
+    }
+    set result
+} {0 0 1 1 c e}
+test dict-22.5 {dict with command} {
+    set a {b c d e}
+    dict with a {
+       lassign "$b $d" d b
+    }
+    dictsort $a
+} {b e d c}
+test dict-22.6 {dict with command} {
+    set a {b c d e}
+    dict with a {
+       unset b
+       # This *won't* go into the dict...
+       set f g
+    }
+    set a
+} {d e}
+test dict-22.7 {dict with command} {
+    set a {b c d e}
+    dict with a {
+       dict unset a b
+    }
+    dictsort $a
+} {b c d e}
+test dict-22.8 {dict with command} {
+    set a [dict create b c]
+    dict with a {
+       set b $a
+    }
+    set a
+} {b {b c}}
+test dict-22.9 {dict with command} {
+    set a {b {c d}}
+    dict with a b {
+       set c $c$c
+    }
+    set a
+} {b {c dd}}
+test dict-22.10 {dict with command: result handling tricky case} {
+    set a {b {c d}}
+    foreach i {0 1} {
+       if {$i} break
+       dict with a b {
+           set a {}
+           # We're checking to see if we lose this break
+           break
+       }
+    }
+    list $i $a
+} {0 {}}
+test dict-22.11 {dict with command: no recursive structures [Bug 1786481]} {
+    set foo {t {t {t {inner 1}}}}
+    dict with foo {
+       dict with t {
+           dict with t {
+               dict with t {
+                   incr inner
+               }
+           }
+       }
+    }
+    string range [append foo OK] end-1 end
+} OK
+
+test dict-23.1 {dict unset missing last level} {
+    set a {b c d e}
+       dict unset a xyz
+       dict size $a
+} 2
+
+test dict-23.2 {dict unset command} -returnCodes error -body {
+    set dictVar a
+    dict unset dictVar a
+} -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+
+test dict-23.3 {dict unset command} -setup {
+    unset -nocomplain dictVar
+} -body {
+    list [info exists dictVar] [dict unset dictVar a] [info exists dictVar]
+} -cleanup {
+    unset dictVar
+} -result {0 {} 1}
+
+test dict-23.4 {dict unset command: write failure} -setup {
+    unset -nocomplain dictVar
+} -body {
+    set dictVar 1
+    dict unset dictVar a
+} -returnCodes error -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+
+test dict-24.1 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;set l} {p 1 p 2 q 3}
+test dict-24.2 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;llength $l} 6
+
+test dict-24.3 {dict/list shimmering with embedded nulls} {
+       # Must be a string containing embedded nulls that would be double quoted in string form
+       set binary_value 1\000\\
+       set dictVar [dict create value $binary_value]
+       lassign $dictVar k v
+       string length $v
+} {3}
+test dict-24.4 {dict/list shimmering with lappend and foreach} {
+       set a [list 1 2 3 4]
+
+       foreach b $a {
+               # convert to dict
+               dict size $a
+               # append to list
+               lappend a x y
+       }
+       llength $a
+} 12
+
+testreport
diff --git a/jim/tests/dict2.test b/jim/tests/dict2.test
new file mode 100755 (executable)
index 0000000..2e9bcd4
--- /dev/null
@@ -0,0 +1,1253 @@
+# This test file covers the dictionary object type and the dict command used
+# to work with values of that type.
+#
+# This file contains a collection of tests for one or more of the Tcl built-in
+# commands. Sourcing this file into Tcl runs the tests and generates output
+# for errors.  No output means no errors were found.
+#
+# Copyright (c) 2003-2009 Donal K. Fellows
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+# jim dicts don't preserve order, so always sort
+# before checking results
+proc dict-sort {dict} {
+    set result {}
+    foreach k [lsort [dict keys $dict]] {
+       lappend result $k [dict get $dict $k]
+    }
+    return $result
+}
+
+test dict-1.1 {dict command basic syntax} -returnCodes error -body {
+    dict
+}  -match glob -result {wrong # args: should be "dict subcommand ?arg* ...?"}
+test dict-1.2 {dict command basic syntax} -returnCodes error -body {
+    dict ?
+} -match glob -result *
+
+test dict-2.1 {dict create command} {
+    dict create
+} {}
+test dict-2.2 {dict create command} {
+    dict create a b
+} {a b}
+test dict-2.3 {dict create command} -body {
+    set result {}
+    set dict [dict create a b c d]
+    # Can't compare directly as ordering of values is undefined
+    foreach key {a c} {
+       set idx [lsearch -exact $dict $key]
+       if {$idx & 1} {
+           error "found $key at odd index $idx in $dict"
+       }
+       lappend result [lindex $dict [expr {$idx+1}]]
+    }
+    return $result
+} -cleanup {
+    unset result dict key idx
+} -result {b d}
+test dict-2.4 {dict create command} -returnCodes error -body {
+    dict create a
+} -result {wrong # args: should be "dict create ?key value ...?"}
+test dict-2.5 {dict create command} -returnCodes error -body {
+    dict create a b c
+} -result {wrong # args: should be "dict create ?key value ...?"}
+test dict-2.6 {dict create command - initialse refcount field!} -body {
+    # Bug 715751 will show up in memory debuggers like purify
+    for {set i 0} {$i<10} {incr i} {
+       set dictv [dict create a 0]
+       if {[catch {
+           set share [dict values $dictv]
+       }]} {
+           set share [array get dictv]
+       }
+       list [dict incr dictv a]
+    }
+} -cleanup {
+    unset i dictv share
+} -result {}
+test dict-2.7 {dict create command - #-quoting in string rep} {
+    dict create # #comment
+} {{#} #comment}
+test dict-2.8 {dict create command - #-quoting in string rep} -body {
+    dict create #a x #b x
+} -match glob -result {{#?} x #? x}
+
+test dict-3.1 {dict get command} {dict get {a b} a} b
+test dict-3.2 {dict get command} {dict get {a b c d} a} b
+test dict-3.3 {dict get command} {dict get {a b c d} c} d
+test dict-3.4 {dict get command} -returnCodes error -body {
+    dict get {a b c d} b
+} -result {key "b" not known in dictionary}
+test dict-3.5 {dict get command} {dict get {a {p q r s} b {u v x y}} a p} q
+test dict-3.6 {dict get command} {dict get {a {p q r s} b {u v x y}} a r} s
+test dict-3.7 {dict get command} {dict get {a {p q r s} b {u v x y}} b u} v
+test dict-3.8 {dict get command} {dict get {a {p q r s} b {u v x y}} b x} y
+test dict-3.9 {dict get command} -returnCodes error -body {
+    dict get {a {p q r s} b {u v x y}} a z
+} -result {key "z" not known in dictionary}
+test dict-3.10 {dict get command} -returnCodes error -body {
+    dict get {a {p q r s} b {u v x y}} c z
+} -result {key "c" not known in dictionary}
+test dict-3.11 {dict get command} {dict get [dict create a b c d] a} b
+test dict-3.12 {dict get command} -returnCodes error -body {
+    dict get
+} -result {wrong # args: should be "dict get dictionary ?key ...?"}
+test dict-3.13 {dict get command} -body {
+    set dict [dict get {a b c d}]
+    if {$dict eq "a b c d"} {
+       return OK
+    } elseif {$dict eq "c d a b"} {
+       return reordered
+    } else {
+       return $dict
+    }
+} -cleanup {
+    unset dict
+} -result OK
+test dict-3.14 {dict get command} -returnCodes error -body {
+    dict get {a b c d} a c
+} -result {missing value to go with key}
+test dict-3.15 {compiled dict get error cleanliness - Bug 2431847} -body {
+    proc x {} {
+       dict set a(z) b c
+       dict get $a(z) d
+    }
+    x
+} -returnCodes error -result {key "d" not known in dictionary}
+test dict-3.16 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;set l} {p 1 p 2 q 3}
+test dict-3.17 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;llength $l} 6
+test dict-3.18 {array set non-dict get command} -constraints jim -returnCodes error -body {
+    set a one
+    array set a {a b c d}
+} -result {missing value to go with key}
+
+test dict-4.1 {dict replace command} {
+    dict replace {a b c d}
+} {a b c d}
+test dict-4.2 {dict replace command} {
+    dict-sort [dict replace {a b c d} e f]
+} {a b c d e f}
+test dict-4.3 {dict replace command} {
+    dict-sort [dict replace {a b c d} c f]
+} {a b c f}
+test dict-4.4 {dict replace command} {
+    dict-sort [dict replace {a b c d} c x a y]
+} {a y c x}
+test dict-4.5 {dict replace command} -returnCodes error -body {
+    dict replace
+} -result {wrong # args: should be "dict replace dictionary ?key value ...?"}
+test dict-4.6 {dict replace command} -returnCodes error -body {
+    dict replace {a a} a
+} -result {wrong # args: should be "dict replace dictionary ?key value ...?"}
+test dict-4.7 {dict replace command} -returnCodes error -body {
+    dict replace {a a a} a b
+} -result {missing value to go with key}
+test dict-4.8 {dict replace command} -returnCodes error -body {
+    dict replace [list a a a] a b
+} -result {missing value to go with key}
+test dict-4.9 {dict replace command} {dict replace [list a a] a b} {a b}
+test dict-4.10 {dict replace command} {dict replace [list a a] a b a c} {a c}
+
+test dict-5.1 {dict remove command} {dict remove {a b c d} a} {c d}
+test dict-5.2 {dict remove command} {dict remove {a b c d} c} {a b}
+test dict-5.3 {dict remove command} {dict remove {a b c d} a c} {}
+test dict-5.4 {dict remove command} {dict remove {a b c d} c a} {}
+test dict-5.5 {dict remove command} {
+    dict remove {a b c d}
+} {a b c d}
+test dict-5.6 {dict remove command} {dict remove {a b} c} {a b}
+test dict-5.7 {dict remove command} -returnCodes error -body {
+    dict remove
+} -result {wrong # args: should be "dict remove dictionary ?key ...?"}
+
+test dict-6.1 {dict keys command} {dict keys {a b}} a
+test dict-6.2 {dict keys command} {dict keys {c d}} c
+test dict-6.3 {dict keys command} {lsort [dict keys {a b c d}]} {a c}
+test dict-6.4 {dict keys command} {dict keys {a b c d} a} a
+test dict-6.5 {dict keys command} {dict keys {a b c d} c} c
+test dict-6.6 {dict keys command} {dict keys {a b c d} e} {}
+test dict-6.7 {dict keys command} {lsort [dict keys {a b c d ca da} c*]} {c ca}
+test dict-6.8 {dict keys command} -returnCodes error -body {
+    dict keys
+} -result {wrong # args: should be "dict keys dictionary ?pattern?"}
+test dict-6.9 {dict keys command} -returnCodes error -body {
+    dict keys {} a b
+} -result {wrong # args: should be "dict keys dictionary ?pattern?"}
+test dict-6.10 {dict keys command} -returnCodes error -body {
+    dict keys a
+} -result {missing value to go with key}
+
+test dict-7.1 {dict values command} {dict values {a b}} b
+test dict-7.2 {dict values command} {dict values {c d}} d
+test dict-7.3 {dict values command} {lsort [dict values {a b c d}]} {b d}
+test dict-7.4 {dict values command} {dict values {a b c d} b} b
+test dict-7.5 {dict values command} {dict values {a b c d} d} d
+test dict-7.6 {dict values command} {dict values {a b c d} e} {}
+test dict-7.7 {dict values command} {lsort [dict values {a b c d ca da} d*]} {d da}
+test dict-7.8 {dict values command} -returnCodes error -body {
+    dict values
+} -result {wrong # args: should be "dict values dictionary ?pattern?"}
+test dict-7.9 {dict values command} -returnCodes error -body {
+    dict values {} a b
+} -result {wrong # args: should be "dict values dictionary ?pattern?"}
+test dict-7.10 {dict values command} -returnCodes error -body {
+    dict values a
+} -result {missing value to go with key}
+
+test dict-8.1 {dict size command} {dict size {}} 0
+test dict-8.2 {dict size command} {dict size {a b}} 1
+test dict-8.3 {dict size command} {dict size {a b c d}} 2
+test dict-8.4 {dict size command} -returnCodes error -body {
+    dict size
+} -result {wrong # args: should be "dict size dictionary"}
+test dict-8.5 {dict size command} -returnCodes error -body {
+    dict size a b
+} -result {wrong # args: should be "dict size dictionary"}
+test dict-8.6 {dict size command} -returnCodes error -body {
+    dict size a
+} -result {missing value to go with key}
+
+test dict-9.1 {dict exists command} {dict exists {a b} a} 1
+test dict-9.2 {dict exists command} {dict exists {a b} b} 0
+test dict-9.3 {dict exists command} {dict exists {a {b c}} a b} 1
+test dict-9.4 {dict exists command} {dict exists {a {b c}} a c} 0
+test dict-9.5 {dict exists command} {dict exists {a {b c}} b c} 0
+test dict-9.6 {dict exists command} -returnCodes error -body {
+    dict exists {a {b c d}} a c
+} -result {missing value to go with key}
+test dict-9.7 {dict exists command} -returnCodes error -body {
+    dict exists
+} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
+test dict-9.8 {dict exists command} -returnCodes error -body {
+    dict exists {}
+} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
+
+#test dict-10.1 {dict info command} -body {
+#    # Actual string returned by this command is undefined; it is
+#    # intended for human consumption and not for use by scripts.
+#    dict info {}
+#} -match glob -result *
+#test dict-10.2 {dict info command} -returnCodes error -body {
+#    dict info
+#} -result {wrong # args: should be "dict info dictionary"}
+#test dict-10.3 {dict info command} -returnCodes error -body {
+#    dict info {} x
+#} -result {wrong # args: should be "dict info dictionary"}
+#test dict-10.4 {dict info command} -returnCodes error -body {
+#    dict info x
+#} -result {missing value to go with key}
+
+test dict-11.1 {dict incr command: unshared value} -body {
+    set dictv [dict create \
+           a [string index "=0=" 1] \
+           b [expr {1+2}] \
+           c [expr {0x80000000+1}]]
+    dict incr dictv a
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a 1 b 3 c 2147483649}
+test dict-11.2 {dict incr command: unshared value} -body {
+    set dictv [dict create \
+           a [string index "=0=" 1] \
+           b [expr {1+2}] \
+           c [expr {0x80000000+1}]]
+    dict incr dictv b
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a 0 b 4 c 2147483649}
+test dict-11.3 {dict incr command: unshared value} -body {
+    set dictv [dict create \
+           a [string index "=0=" 1] \
+           b [expr {1+2}] \
+           c [expr {0x80000000+1}]]
+    dict incr dictv c
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a 0 b 3 c 2147483650}
+test dict-11.4 {dict incr command: shared value} -body {
+    set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
+    set sharing [dict values $dictv]
+    dict incr dictv a
+       dict-sort $dictv
+} -cleanup {
+    unset dictv sharing
+} -result {a 1 b 3 c 2147483649}
+test dict-11.5 {dict incr command: shared value} -body {
+    set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
+    set sharing [dict values $dictv]
+    dict incr dictv b
+       dict-sort $dictv
+} -cleanup {
+    unset dictv sharing
+} -result {a 0 b 4 c 2147483649}
+test dict-11.6 {dict incr command: shared value} -body {
+    set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
+    set sharing [dict values $dictv]
+    dict incr dictv c
+       dict-sort $dictv
+} -cleanup {
+    unset dictv sharing
+} -result {a 0 b 3 c 2147483650}
+test dict-11.7 {dict incr command: unknown values} -body {
+    set dictv [dict create a 0 b [expr {1+2}] c [expr {0x80000000+1}]]
+    dict incr dictv d
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a 0 b 3 c 2147483649 d 1}
+test dict-11.8 {dict incr command} -body {
+    set dictv {a 1}
+    dict incr dictv a 2
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a 3}
+test dict-11.9 {dict incr command} -returnCodes error -body {
+    set dictv {a dummy}
+    dict incr dictv a
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {expected integer but got "dummy"}
+test dict-11.10 {dict incr command} -returnCodes error -body {
+    set dictv {a 1}
+    dict incr dictv a dummy
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {expected integer but got "dummy"}
+test dict-11.11 {dict incr command} -setup {
+    unset -nocomplain dictv
+} -body {
+    dict incr dictv a
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a 1}
+test dict-11.12 {dict incr command} -returnCodes error -body {
+    set dictv a
+    dict incr dictv a
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {missing value to go with key}
+test dict-11.13 {dict incr command} -returnCodes error -body {
+    set dictv a
+    dict incr dictv a a a
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {wrong # args: should be "dict incr varName key ?increment?"}
+test dict-11.14 {dict incr command} -returnCodes error -body {
+    set dictv a
+    dict incr dictv
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {wrong # args: should be "dict incr varName key ?increment?"}
+test dict-11.15 {dict incr command: write failure} -setup {
+    unset -nocomplain dictVar
+} -body {
+    set dictVar 1
+    dict incr dictVar a
+       dict-sort $dictv
+} -returnCodes error -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+test dict-11.16 {dict incr command: compilation} {
+    apply {{} {
+       set v {a 0 b 0 c 0}
+       dict incr v a
+       dict incr v b 1
+       dict incr v c 2
+       dict incr v d 3
+       list [dict get $v a] [dict get $v b] [dict get $v c] [dict get $v d]
+    }}
+} {1 1 2 3}
+test dict-11.17 {dict incr command: compilation} {
+    apply {{} {
+       set dictv {a 1}
+       dict incr dictv a 2
+       dict-sort $dictv
+    }}
+} {a 3}
+
+test dict-12.1 {dict lappend command} -body {
+    set dictv {a a}
+    dict lappend dictv a
+} -cleanup {
+    unset dictv
+} -result {a a}
+test dict-12.2 {dict lappend command} -body {
+    set dictv {a a}
+    set sharing [dict values $dictv]
+    dict lappend dictv a b
+       dict-sort $dictv
+} -cleanup {
+    unset dictv sharing
+} -result {a {a b}}
+test dict-12.3 {dict lappend command} -body {
+    set dictv {a a}
+    dict lappend dictv a b c
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a {a b c}}
+test dict-12.2.1 {dict lappend command} -body {
+    set dictv [dict create a [string index =a= 1]]
+    dict lappend dictv a b
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a {a b}}
+test dict-12.4 {dict lappend command} -body {
+    set dictv {}
+    dict lappend dictv a x y z
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a {x y z}}
+test dict-12.5 {dict lappend command} -body {
+    unset -nocomplain dictv
+    dict lappend dictv a b
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {a b}
+test dict-12.6 {dict lappend command} -returnCodes error -body {
+    set dictv a
+    dict lappend dictv a a
+       dict-sort $dictv
+} -cleanup {
+    unset dictv
+} -result {missing value to go with key}
+test dict-12.7 {dict lappend command} -returnCodes error -body {
+    dict lappend
+} -result {wrong # args: should be "dict lappend varName key ?value ...?"}
+test dict-12.8 {dict lappend command} -returnCodes error -body {
+    dict lappend dictv
+} -result {wrong # args: should be "dict lappend varName key ?value ...?"}
+test dict-12.9 {dict lappend command} -returnCodes error -constraints tcl -body {
+    set dictv [dict create a "\{"]
+    dict lappend dictv a a
+} -cleanup {
+    unset dictv
+} -result {unmatched open brace in list}
+test dict-12.10 {dict lappend command: write failure} -setup {
+    unset -nocomplain dictVar
+} -body {
+    set dictVar 1
+    dict lappend dictVar a x
+} -returnCodes error -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+test dict-12.11 {compiled dict append: invalidate string rep - Bug 3079830} {
+    dict-sort [apply {{} {set d {a 1 b 2 c 3}; dict lappend d b 22}}]
+} {a 1 b {2 22} c 3}
+
+test dict-13.1 {dict append command} -body {
+    set dictv {a a}
+    dict append dictv a
+} -cleanup {
+    unset dictv
+} -result {a a}
+test dict-13.2 {dict append command} -body {
+    set dictv {a a}
+    set sharing [dict values $dictv]
+    dict append dictv a b
+} -cleanup {
+    unset dictv sharing
+} -result {a ab}
+test dict-13.3 {dict append command} -body {
+    set dictv {a a}
+    dict append dictv a b c
+} -cleanup {
+    unset dictv
+} -result {a abc}
+test dict-13.2.1 {dict append command} -body {
+    set dictv [dict create a [string index =a= 1]]
+    dict append dictv a b
+} -cleanup {
+    unset dictv
+} -result {a ab}
+test dict-13.4 {dict append command} -body {
+    set dictv {}
+    dict append dictv a x y z
+} -cleanup {
+    unset dictv
+} -result {a xyz}
+test dict-13.5 {dict append command} -body {
+    unset -nocomplain dictv
+    dict append dictv a b
+} -cleanup {
+    unset dictv
+} -result {a b}
+test dict-13.6 {dict append command} -returnCodes error -body {
+    set dictv a
+    dict append dictv a a
+} -cleanup {
+    unset dictv
+} -result {missing value to go with key}
+test dict-13.7 {dict append command} -returnCodes error -body {
+    dict append
+} -result {wrong # args: should be "dict append varName key ?value ...?"}
+test dict-13.8 {dict append command} -returnCodes error -body {
+    dict append dictv
+} -result {wrong # args: should be "dict append varName key ?value ...?"}
+test dict-13.9 {dict append command: write failure} -setup {
+    unset -nocomplain dictVar
+} -body {
+    set dictVar 1
+    dict append dictVar a x
+} -returnCodes error -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+test dict-13.10 {compiled dict append: crash case} {
+    apply {{} {dict append dictVar a o k}}
+} {a ok}
+test dict-13.11 {compiled dict append: invalidate string rep - Bug 3079830} {
+    dict-sort [apply {{} {set d {a 1 b 2 c 3}; dict append d b 22}}]
+} {a 1 b 222 c 3}
+
+test dict-14.1 {dict for command: syntax} -returnCodes error -body {
+    dict for
+} -match glob -result {wrong # args: should be *}
+test dict-14.2 {dict for command: syntax} -returnCodes error -body {
+    dict for x
+} -match glob -result {wrong # args: should be *}
+test dict-14.3 {dict for command: syntax} -returnCodes error -body {
+    dict for x x
+} -match glob -result {wrong # args: should be *}
+test dict-14.4 {dict for command: syntax} -returnCodes error -body {
+    dict for x x x x
+} -match glob -result {wrong # args: should be *}
+test dict-14.5 {dict for command: syntax} -returnCodes error -body {
+    dict for x x x
+} -result {must have exactly two variable names}
+test dict-14.6 {dict for command: syntax} -returnCodes error -body {
+    dict for {x x x} x x
+} -result {must have exactly two variable names}
+test dict-14.7 {dict for command: syntax} -returnCodes error -constraints tcl -body {
+    dict for "\{x" x x
+} -result {unmatched open brace in list}
+test dict-14.8 {dict for command} -constraints tcl -body {
+    # This test confirms that [dict keys], [dict values] and [dict for]
+    # all traverse a dictionary in the same order.
+       # Note that Jim Tcl does *not* preserver order
+    set dictv {a A b B c C}
+    set keys {}
+    set values {}
+    dict for {k v} $dictv {
+       lappend keys $k
+       lappend values $v
+    }
+    set result [expr {
+       $keys eq [dict keys $dictv] && $values eq [dict values $dictv]
+    }]
+    expr {$result ? "YES" : [list "NO" $dictv $keys $values]}
+} -cleanup {
+    unset result keys values k v dictv
+} -result YES
+test dict-14.9 {dict for command} {
+    dict for {k v} {} {
+       error "unexpected execution of 'dict for' body"
+    }
+} {}
+test dict-14.10 {dict for command: script results} -body {
+    set times 0
+    dict for {k v} {a a b b} {
+       incr times
+       continue
+       error "shouldn't get here"
+    }
+    return $times
+} -cleanup {
+    unset times k v
+} -result 2
+test dict-14.11 {dict for command: script results} -body {
+    set times 0
+    dict for {k v} {a a b b} {
+       incr times
+       break
+       error "shouldn't get here"
+    }
+    return $times
+} -cleanup {
+    unset times k v
+} -result 1
+test dict-14.12 {dict for command: script results} -body {
+    set times 0
+    list [catch {
+       dict for {k v} {a a b b} {
+           incr times
+           error test
+       }
+    } msg] $msg $times
+} -cleanup {
+    unset times k v msg
+} -result {1 test 1}
+test dict-14.13 {dict for command: script results} {
+    apply {{} {
+       dict for {k v} {a b} {
+           return ok,$k,$v
+           error "skipped return completely"
+       }
+       error "return didn't go far enough"
+    }}
+} ok,a,b
+test dict-14.14 {dict for command: handle representation loss} -body {
+    set dictVar {a b c d e f g h}
+    set keys {}
+    set values {}
+    dict for {k v} $dictVar {
+       if {[llength $dictVar]} {
+           lappend keys $k
+           lappend values $v
+       }
+    }
+    list [lsort $keys] [lsort $values]
+} -cleanup {
+    unset dictVar keys values k v
+} -result {{a c e g} {b d f h}}
+test dict-14.15 {dict for command: keys are unique and iterated over once only} -setup {
+    unset -nocomplain accum
+    array set accum {}
+} -body {
+    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+    dict for {k v} $dictVar {
+       append accum($k) $v,
+    }
+    set result [lsort [array names accum]]
+    lappend result :
+    foreach k $result {
+       catch {lappend result $accum($k)}
+    }
+    return $result
+} -cleanup {
+    unset dictVar k v result accum
+} -result {a1 a2 b1 b2 bar foo : a, b, c, d, foo, bar,}
+test dict-14.16 {dict for command in compilation context} {
+    apply {{} {
+       set res {x x x x x x}
+       dict for {k v} {a 0 b 1 c 2 d 3 e 4 f 5} {
+           lset res $v $k
+           continue
+       }
+       return $res
+    }}
+} {a b c d e f}
+test dict-14.17 {dict for command in compilation context} {
+    # Bug 1379349
+    apply {{} {
+       set d [dict create a 1]         ;# Dict must be unshared!
+       dict for {k v} $d {
+           dict set d $k 0             ;# Any modification will do
+       }
+       return $d
+    }}
+} {a 0}
+test dict-14.18 {dict for command in compilation context} {
+    # Bug 1382528
+    apply {{} {
+       dict for {k v} {} {}            ;# Note empty dict
+       catch { error foo }             ;# Note compiled [catch]
+    }}
+} 1
+test dict-14.19 {dict for and invalid dicts: bug 1531184} -body {
+    di[list]ct for {k v} x {}
+} -returnCodes 1 -result {missing value to go with key}
+test dict-14.20 {dict for stack space compilation: bug 1903325} {
+    apply {{x y args} {
+       dict for {a b} $x {}
+       concat "c=$y,$args"
+    }} {} 1 2 3
+} {c=1,2 3}
+# There's probably a lot more tests to add here. Really ought to use a
+# coverage tool for this job...
+
+test dict-15.1 {dict set command} -body {
+    set dictVar {}
+    dict set dictVar a x
+} -cleanup {
+    unset dictVar
+} -result {a x}
+test dict-15.2 {dict set command} -body {
+    set dictvar {a {}}
+    dict set dictvar a b x
+} -cleanup {
+    unset dictvar
+} -result {a {b x}}
+test dict-15.3 {dict set command} -body {
+    set dictvar {a {b {}}}
+    dict set dictvar a b c x
+} -cleanup {
+    unset dictvar
+} -result {a {b {c x}}}
+test dict-15.4 {dict set command} -body {
+    set dictVar {a y}
+    dict set dictVar a x
+} -cleanup {
+    unset dictVar
+} -result {a x}
+test dict-15.5 {dict set command} -body {
+    set dictVar {a {b y}}
+    dict set dictVar a b x
+} -cleanup {
+    unset dictVar
+} -result {a {b x}}
+test dict-15.6 {dict set command} -body {
+    set dictVar {a {b {c y}}}
+    dict set dictVar a b c x
+} -cleanup {
+    unset dictVar
+} -result {a {b {c x}}}
+test dict-15.7 {dict set command: path creation} -body {
+    set dictVar {}
+    dict set dictVar a b x
+} -cleanup {
+    unset dictVar
+} -result {a {b x}}
+test dict-15.8 {dict set command: creates variables} -setup {
+    unset -nocomplain dictVar
+} -body {
+    dict set dictVar a x
+    return $dictVar
+} -cleanup {
+    unset dictVar
+} -result {a x}
+test dict-15.9 {dict set command: write failure} -setup {
+    unset -nocomplain dictVar
+} -body {
+    set dictVar 1
+    dict set dictVar a x
+} -returnCodes error -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+test dict-15.10 {dict set command: syntax} -returnCodes error -body {
+    dict set
+} -result {wrong # args: should be "dict set varName key ?key ...? value"}
+test dict-15.11 {dict set command: syntax} -returnCodes error -body {
+    dict set a
+} -result {wrong # args: should be "dict set varName key ?key ...? value"}
+test dict-15.12 {dict set command: syntax} -returnCodes error -body {
+    dict set a a
+} -result {wrong # args: should be "dict set varName key ?key ...? value"}
+test dict-15.13 {dict set command} -returnCodes error -body {
+    set dictVar a
+    dict set dictVar b c
+} -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+
+test dict-16.1 {dict unset command} -body {
+    set dictVar {a b c d}
+    dict unset dictVar a
+} -cleanup {
+    unset dictVar
+} -result {c d}
+test dict-16.2 {dict unset command} -body {
+    set dictVar {a b c d}
+    dict unset dictVar c
+} -cleanup {
+    unset dictVar
+} -result {a b}
+test dict-16.3 {dict unset command} -body {
+    set dictVar {a b}
+    dict unset dictVar c
+} -cleanup {
+    unset dictVar
+} -result {a b}
+test dict-16.4 {dict unset command} -body {
+    set dictVar {a {b c d e}}
+    dict unset dictVar a b
+} -cleanup {
+    unset dictVar
+} -result {a {d e}}
+test dict-16.5 {dict unset command} -returnCodes error -body {
+    set dictVar a
+    dict unset dictVar a
+} -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+test dict-16.6 {dict unset command} -returnCodes error -body {
+    set dictVar {a b}
+    dict unset dictVar c d
+} -cleanup {
+    unset dictVar
+} -result {key "c" not known in dictionary}
+test dict-16.7 {dict unset command} -setup {
+    unset -nocomplain dictVar
+} -body {
+    list [info exists dictVar] [dict unset dictVar a] [info exists dictVar]
+} -cleanup {
+    unset dictVar
+} -result {0 {} 1}
+test dict-16.8 {dict unset command} -returnCodes error -body {
+    dict unset dictVar
+} -result {wrong # args: should be "dict unset varName key ?key ...?"}
+test dict-16.9 {dict unset command: write failure} -setup {
+    unset -nocomplain dictVar
+} -body {
+    set dictVar 1
+    dict unset dictVar a
+} -returnCodes error -cleanup {
+    unset dictVar
+} -result {missing value to go with key}
+
+#test dict-17.1 {dict filter command: key} -body {
+#    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+#    dict filter $dictVar key a2
+#} -cleanup {
+#    unset dictVar
+#} -result {a2 b}
+#test dict-17.2 {dict filter command: key} -body {
+#    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+#    dict size [dict filter $dictVar key *]
+#} -cleanup {
+#    unset dictVar
+#} -result 6
+#test dict-17.3 {dict filter command: key} -body {
+#    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+#    dict filter $dictVar key ???
+#} -cleanup {
+#    unset dictVar
+#} -result {foo bar bar foo}
+#test dict-17.4 {dict filter command: key - no patterns} {
+#    dict filter {a b c d} key
+#} {}
+#test dict-17.4.1 {dict filter command: key - many patterns} {
+#    dict filter {a1 a a2 b b1 c b2 d foo bar bar foo} key a? b?
+#} {a1 a a2 b b1 c b2 d}
+#test dict-17.5 {dict filter command: key - bad dict} -returnCodes error -body {
+#    dict filter {a b c} key
+#} -result {missing value to go with key}
+#test dict-17.6 {dict filter command: value} -body {
+#    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+#    dict filter $dictVar value c
+#} -cleanup {
+#    unset dictVar
+#} -result {b1 c}
+#test dict-17.7 {dict filter command: value} -body {
+#    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+#    dict size [dict filter $dictVar value *]
+#} -cleanup {
+#    unset dictVar
+#} -result 6
+#test dict-17.8 {dict filter command: value} -body {
+#    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+#    dict filter $dictVar value ???
+#} -cleanup {
+#    unset dictVar
+#} -result {foo bar bar foo}
+#test dict-17.9 {dict filter command: value - no patterns} {
+#    dict filter {a b c d} value
+#} {}
+#test dict-17.9.1 {dict filter command: value - many patterns} {
+#    dict filter {a a1 b a2 c b1 foo bar bar foo d b2} value a? b?
+#} {a a1 b a2 c b1 d b2}
+#test dict-17.10 {dict filter command: value - bad dict} -body {
+#    dict filter {a b c} value a
+#} -returnCodes error -result {missing value to go with key}
+#test dict-17.11 {dict filter command: script} -body {
+#    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+#    set n 0
+#    list [dict filter $dictVar script {k v} {
+#      incr n
+#      expr {[string length $k] == [string length $v]}
+#    }] $n
+#} -cleanup {
+#    unset dictVar n k v
+#} -result {{foo bar bar foo} 6}
+#test dict-17.12 {dict filter command: script} -returnCodes error -body {
+#    dict filter {a b} script {k v} {
+#      concat $k $v
+#    }
+#} -cleanup {
+#    unset k v
+#} -result {expected boolean value but got "a b"}
+#test dict-17.13 {dict filter command: script} -body {
+#    list [catch {dict filter {a b} script {k v} {error x}} msg] $msg \
+#          $::errorInfo
+#} -cleanup {
+#    unset k v msg
+#} -result {1 x {x
+#    while executing
+#"error x"
+#    ("dict filter" script line 1)
+#    invoked from within
+#"dict filter {a b} script {k v} {error x}"}}
+#test dict-17.14 {dict filter command: script} -setup {
+#    set n 0
+#} -body {
+#    list [dict filter {a b c d} script {k v} {
+#      incr n
+#      break
+#      error boom!
+#    }] $n
+#} -cleanup {
+#    unset n k v
+#} -result {{} 1}
+#test dict-17.15 {dict filter command: script} -setup {
+#    set n 0
+#} -body {
+#    list [dict filter {a b c d} script {k v} {
+#      incr n
+#      continue
+#      error boom!
+#    }] $n
+#} -cleanup {
+#    unset n k v
+#} -result {{} 2}
+#test dict-17.16 {dict filter command: script} {
+#    apply {{} {
+#      dict filter {a b} script {k v} {
+#          return ok,$k,$v
+#          error "skipped return completely"
+#      }
+#      error "return didn't go far enough"
+#    }}
+#} ok,a,b
+#test dict-17.17 {dict filter command: script} -body {
+#    dict filter {a b} script {k k} {continue}
+#    return $k
+#} -cleanup {
+#    unset k
+#} -result b
+#test dict-17.18 {dict filter command: script} -returnCodes error -body {
+#    dict filter {a b} script {k k}
+#} -result {wrong # args: should be "dict filter dictionary script {keyVar valueVar} filterScript"}
+#test dict-17.19 {dict filter command: script} -returnCodes error -body {
+#    dict filter {a b} script k {continue}
+#} -result {must have exactly two variable names}
+#test dict-17.20 {dict filter command: script} -returnCodes error -body {
+#    dict filter {a b} script "\{k v" {continue}
+#} -result {unmatched open brace in list}
+#test dict-17.21 {dict filter command} -returnCodes error -body {
+#    dict filter {a b}
+#} -result {wrong # args: should be "dict filter dictionary filterType ?arg ...?"}
+#test dict-17.22 {dict filter command} -returnCodes error -body {
+#    dict filter {a b} JUNK
+#} -result {bad filterType "JUNK": must be key, script, or value}
+#test dict-17.23 {dict filter command} -returnCodes error -body {
+#    dict filter a key *
+#} -result {missing value to go with key}
+
+test dict-18.1 {dict-list relationship} -body {
+    # Test that any internal conversion between list and dict does not change
+    # the object
+    set l [list 1 2 3 4 5 6 7 8 9 0 q w e r t y]
+    dict values $l
+    return $l
+} -cleanup {
+    unset l
+} -result {1 2 3 4 5 6 7 8 9 0 q w e r t y}
+test dict-18.2 {dict-list relationship} -body {
+    # Test that the dictionary is a valid list
+    set d [dict create "abc def" 0 "a\{b" 1 "c\}d" 2]
+    for {set t 0} {$t < 5} {incr t} {
+       llength $d
+       dict lappend d "abc def" "\}\{"
+       dict append  d "a\{b" "\}"
+       dict incr    d "c\}d" 1
+    }
+    llength $d
+} -cleanup {
+    unset d t
+} -result 6
+test dict-18.3 {dict-list relationship} -body {
+    set ld [list a b c d c e f g]
+    list [string length $ld] [dict size $ld] [llength $ld]
+} -cleanup {
+    unset ld
+} -result {15 3 8}
+test dict-18.4 {dict-list relationship} -body {
+    set ld [list a b c d c e f g]
+    list [llength $ld] [dict size $ld] [llength $ld]
+} -cleanup {
+    unset ld
+} -result {8 3 8}
+
+test dict-20.1 {dict merge command} {
+    dict merge
+} {}
+test dict-20.2 {dict merge command} {
+    dict-sort [dict merge {a b c d e f}]
+} {a b c d e f}
+test dict-20.3 {dict merge command} -body {
+    dict-sort [dict merge {a b c d e}]
+} -result {missing value to go with key} -returnCodes error
+test dict-20.4 {dict merge command} {
+    dict-sort [dict merge {a b c d} {e f g h}]
+} {a b c d e f g h}
+test dict-20.5 {dict merge command} -body {
+    dict-sort [dict merge {a b c d e} {e f g h}]
+} -result {missing value to go with key} -returnCodes error
+test dict-20.6 {dict merge command} -body {
+    dict-sort [dict merge {a b c d} {e f g h i}]
+} -result {missing value to go with key} -returnCodes error
+test dict-20.7 {dict merge command} {
+    dict-sort [dict merge {a b c d e f} {e x g h}]
+} {a b c d e x g h}
+test dict-20.8 {dict merge command} {
+    dict-sort [dict merge {a b c d} {a x c y}]
+} {a x c y}
+test dict-20.9 {dict merge command} {
+    dict-sort [dict merge {a b c d} {c y a x}]
+} {a x c y}
+test dict-20.10 {dict merge command} {
+    dict-sort [dict merge {a b c d e f} {a x 1 2 3 4} {a - 1 -}]
+} {1 - 3 4 a - c d e f}
+
+test dict-21.1 {dict update command} -returnCodes 1 -body {
+    dict update
+} -match glob -result {wrong # args: should be "dict update varName * script"}
+test dict-21.2 {dict update command} -returnCodes 1 -body {
+    dict update v
+} -match glob -result {wrong # args: should be "dict update varName * script"}
+test dict-21.3 {dict update command} -returnCodes 1 -body {
+    dict update v k
+} -match glob -result {wrong # args: should be "dict update varName * script"}
+test dict-21.4 {dict update command} -returnCodes 1 -body {
+    dict update v k v
+} -match glob -result {wrong # args: should be "dict update varName * script"}
+test dict-21.5 {dict update command} -body {
+    set a {b c}
+    set result {}
+    set bb {}
+    dict update a b bb {
+       lappend result $a $bb
+    }
+    lappend result $a
+} -cleanup {
+    unset a result bb
+} -result {{b c} c {b c}}
+test dict-21.6 {dict update command} -body {
+    set a {b c}
+    set result {}
+    set bb {}
+    dict update a b bb {
+       lappend result $a $bb [set bb d]
+    }
+    lappend result $a
+} -cleanup {
+    unset a result bb
+} -result {{b c} c d {b d}}
+test dict-21.7 {dict update command} -body {
+    set a {b c}
+    set result {}
+    set bb {}
+    dict update a b bb {
+       lappend result $a $bb [unset bb]
+    }
+    lappend result $a
+} -cleanup {
+    unset a result
+} -result {{b c} c {} {}}
+test dict-21.8 {dict update command} -body {
+    set a {b c d e}
+    dict update a b v1 d v2 {
+       lassign "$v1 $v2" v2 v1
+    }
+    dict-sort $a
+} -cleanup {
+    unset a v1 v2
+} -result {b e d c}
+test dict-21.9 {dict update command} -body {
+    set a {b c d e}
+    dict update a b v1 d v2 {unset a}
+    info exist a
+} -cleanup {
+    unset v1 v2
+} -result 0
+test dict-21.10 {dict update command} -body {
+    set a {b {c d}}
+    dict update a b v1 {
+       dict update v1 c v2 {
+           set v2 foo
+       }
+    }
+    dict-sort $a
+} -cleanup {
+    unset a v1 v2
+} -result {b {c foo}}
+test dict-21.11 {dict update command} -body {
+    set a {b c d e}
+    dict update a b v1 d v2 {
+       dict set a f g
+    }
+    dict-sort $a
+} -cleanup {
+    unset a v1 v2
+} -result {b c d e f g}
+test dict-21.12 {dict update command} -body {
+    set a {b c d e}
+    dict update a b v1 d v2 f v3 {
+       set v3 g
+    }
+    dict-sort $a
+} -cleanup {
+    unset a v1 v2 v3
+} -result {b c d e f g}
+test dict-21.13 {dict update command: compilation} {
+    apply {d {
+       while 1 {
+           dict update d a alpha b beta {
+               set beta $alpha
+               unset alpha
+               break
+           }
+       }
+       dict-sort $d
+    }} {a 1 c 2}
+} {b 1 c 2}
+test dict-21.14 {dict update command: compilation} tcl {
+    apply {x {
+       set indices {2 3}
+       trace add variable aa write "string length \$indices ;#"
+       dict update x k aa l bb {}
+    }} {k 1 l 2}
+} {}
+test dict-21.15 {dict update command: compilation} tcl {
+    apply {x {
+       set indices {2 3}
+       trace add variable aa read "string length \$indices ;#"
+       dict update x k aa l bb {}
+    }} {k 1 l 2}
+} {}
+test dict-21.16 {dict update command: no recursive structures [Bug 1786481]} -body {
+    set foo {a {b {c {d {e 1}}}}}
+    dict update foo a t {
+       dict update t b t {
+           dict update t c t {
+               dict update t d t {
+                   dict incr t e
+               }
+           }
+       }
+    }
+    string range [append foo OK] end-1 end
+} -cleanup {
+    unset foo t
+} -result OK
+test dict-21.17 {dict update command: no recursive structures [Bug 1786481]} {
+    apply {{} {
+       set foo {a {b {c {d {e 1}}}}}
+       dict update foo a t {
+           dict update t b t {
+               dict update t c t {
+                   dict update t d t {
+                       dict incr t e
+                   }
+               }
+           }
+       }
+       string range [append foo OK] end-1 end
+    }}
+} OK
+
+test dict-22.1 {dict with command} -body {
+    dict with
+} -returnCodes 1 -result {wrong # args: should be "dict with dictVar ?key ...? script"}
+test dict-22.2 {dict with command} -body {
+    dict with v
+} -returnCodes 1 -result {wrong # args: should be "dict with dictVar ?key ...? script"}
+test dict-22.3 {dict with command} -body {
+    unset -nocomplain v
+    dict with v {error "in body"}
+} -returnCodes 1 -result {can't read "v": no such variable}
+test dict-22.4 {dict with command} -body {
+    set a {b c d e}
+    unset -nocomplain b d
+    set result [list [info exist b] [info exist d]]
+    dict with a {
+       lappend result [info exist b] [info exist d] $b $d
+    }
+    return $result
+} -cleanup {
+    unset a b d result
+} -result {0 0 1 1 c e}
+test dict-22.5 {dict with command} -body {
+    set a {b c d e}
+    dict with a {
+       lassign "$b $d" d b
+    }
+    dict-sort $a
+} -cleanup {
+    unset a b d
+} -result {b e d c}
+test dict-22.6 {dict with command} -body {
+    set a {b c d e}
+    dict with a {
+       unset b
+       # This *won't* go into the dict...
+       set f g
+    }
+    return $a
+} -cleanup {
+    unset a d f
+} -result {d e}
+test dict-22.7 {dict with command} -body {
+    set a {b c d e}
+    dict with a {
+       dict unset a b
+    }
+    return [dict-sort $a]
+} -cleanup {
+    unset a
+} -result {b c d e}
+test dict-22.8 {dict with command} -body {
+    set a [dict create b c]
+    dict with a {
+       set b $a
+    }
+    return $a
+} -cleanup {
+    unset a b
+} -result {b {b c}}
+test dict-22.9 {dict with command} -body {
+    set a {b {c d}}
+    dict with a b {
+       set c $c$c
+    }
+    return $a
+} -cleanup {
+    unset a c
+} -result {b {c dd}}
+test dict-22.10 {dict with command: result handling tricky case} -body {
+    set a {b {c d}}
+    foreach i {0 1} {
+       if {$i} break
+       dict with a b {
+           set a {}
+           # We're checking to see if we lose this break
+           break
+       }
+    }
+    list $i $a
+} -cleanup {
+    unset a i c
+} -result {0 {}}
+test dict-22.11 {dict with command: no recursive structures [Bug 1786481]} -body {
+    set foo {t {t {t {inner 1}}}}
+    dict with foo {
+       dict with t {
+           dict with t {
+               dict with t {
+                   incr inner
+               }
+           }
+       }
+    }
+    string range [append foo OK] end-1 end
+} -cleanup {
+    unset foo t inner
+} -result OK
+\f
+testreport
diff --git a/jim/tests/dummy.tcl b/jim/tests/dummy.tcl
new file mode 100755 (executable)
index 0000000..e776ef7
--- /dev/null
@@ -0,0 +1,6 @@
+# generates an error
+proc dummyproc {} {
+       error "from dummyproc"
+}
+
+dummyproc
diff --git a/jim/tests/error.test b/jim/tests/error.test
new file mode 100755 (executable)
index 0000000..65dd506
--- /dev/null
@@ -0,0 +1,55 @@
+source [file dirname [info script]]/testing.tcl
+needs constraint jim; needs cmd package
+proc a {} {
+       error "error thrown from a"
+}
+
+proc b {} {
+       set rc [catch {a} msg]
+       if {$rc} {
+               error $msg [info stacktrace]
+       }
+}
+
+test error-1.1 "Rethrow caught error" {
+       set rc [catch {b} msg]
+       #puts stderr "error-1.1\n[errorInfo $msg]\n"
+
+       list $rc $msg [info stacktrace]
+} {1 {error thrown from a} {{} error.test 4 a error.test 8 b error.test 15}}
+
+proc c {} {
+       a
+}
+
+proc d {} {
+       c
+}
+
+proc e {} {
+       d
+}
+
+test error-1.2 "Modify stacktrace" {
+       set rc [catch {e} msg]
+       set st [info stacktrace]
+       # Now elide one entry from the stacktrace
+       #puts [errorInfo $msg]
+       set newst {}
+       foreach {p f l} $st {
+               if {$p ne "d"} {
+                       lappend newst $p $f $l
+               }
+       }
+       # Now rethrow with the new stack
+       set rc [catch {error $msg $newst} msg]
+       #puts [errorInfo $msg]
+       info stacktrace
+} {{} error.test 4 a error.test 22 c error.test 26 e error.test 34}
+
+# Package should be able to invoke exit, which should exit if not caught
+test error-2.1 "Exit from package" {
+       list [catch -exit {package require exitpackage} msg] $msg
+} {6 {Can't load package exitpackage}}
+
+testreport
diff --git a/jim/tests/errors.tcl b/jim/tests/errors.tcl
new file mode 100755 (executable)
index 0000000..1105dfa
--- /dev/null
@@ -0,0 +1,59 @@
+# Package which can generate a variety of errors at known locations
+
+proc error_generator {type} {
+       switch $type {
+               badcmd {
+                       bogus command called
+               } 
+               badvar {
+                       set bogus
+               } 
+               error {
+                       error bogus
+               } 
+               interpbadvar {
+                       set x "some $bogus text"
+               } 
+               interpbadcmd {
+                       set x "some $bogus text"
+               } 
+               package {
+                       package require dummy
+               } 
+               source {
+                       source dummy.tcl
+               } 
+               badpackage {
+                       package require bogus
+               } 
+               returncode {
+                       return -code error failure
+               } 
+               default {
+                       puts "Unknown type=$type"
+               }
+       }
+}
+
+
+
+# line 40: Some empty lines above so that line numbers don't change
+proc error_caller {type {method call}} {
+       switch $method {
+               call {
+                       error_generator $type
+               } 
+               uplevel {
+                       uplevel 1 [list error_generator $type]
+               } 
+               eval {
+                       eval [list error_generator $type]
+               } 
+               evalstr {
+                       eval error_generator $type
+               } 
+               default {
+                       puts "Unknown method=$method"
+               }
+       }
+}
diff --git a/jim/tests/event.test b/jim/tests/event.test
new file mode 100755 (executable)
index 0000000..856e0cc
--- /dev/null
@@ -0,0 +1,203 @@
+# This file contains a collection of tests for the procedures in the file
+# tclEvent.c, which includes the "update", and "vwait" Tcl
+# commands.  Sourcing this file into Tcl runs the tests and generates
+# output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1995-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd after eventloop
+testConstraint socket [expr {[info commands socket] ne ""}]
+testConstraint exec [expr {[info commands exec] ne ""}]
+testConstraint signal [expr {[info commands signal] ne ""}]
+
+test event-5.1 {Tcl_BackgroundError, HandleBgErrors procedures} jim {
+    catch {rename bgerror {}}
+    proc bgerror msg {
+       lappend ::x $msg
+    }
+    after idle {error "a simple error"}
+    after idle {open non_existent}
+    after idle {set errorInfo foobar; set errorCode xyzzy}
+    set x {}
+    update idletasks
+    rename bgerror {}
+    set x
+} {{a simple error} {non_existent: No such file or directory}}
+
+test event-7.1 {bgerror / regular} {
+    set errRes {}
+    proc bgerror {err} {
+       global errRes;
+       set errRes $err;
+    }
+    after 0 {error err1}
+    vwait errRes;
+    set errRes;
+} err1
+
+test event-7.2 {bgerror / accumulation} {
+    set errRes {}
+    proc bgerror {err} {
+       global errRes;
+       lappend errRes $err;
+    }
+    after 0 {error err1}
+    after 0 {error err2}
+    after 0 {error err3}
+    update
+    set errRes;
+} {err1 err2 err3}
+
+test event-7.3 {bgerror / accumulation / break} {
+    set errRes {}
+    proc bgerror {err} {
+       global errRes;
+       lappend errRes $err;
+       return -code break "skip!";
+    }
+    after 0 {error err1}
+    after 0 {error err2}
+    after 0 {error err3}
+    update
+    set errRes;
+} err1
+
+# end of bgerror tests
+catch {rename bgerror {}}
+
+
+test event-10.1 {Tcl_Exit procedure} exec {
+    set cmd [list exec [info nameofexecutable] "<<exit 3"]
+    list [catch $cmd msg] [lindex $errorCode 0] \
+        [lindex $errorCode 2]
+} {1 CHILDSTATUS 3}
+
+test event-11.1 {Tcl_VwaitCmd procedure} {
+    list [catch {vwait} msg] $msg
+} {1 {wrong # args: should be "vwait name"}}
+test event-11.2 {Tcl_VwaitCmd procedure} {
+    list [catch {vwait a b} msg] $msg
+} {1 {wrong # args: should be "vwait name"}}
+test event-11.3 {Tcl_VwaitCmd procedure} jim {
+    catch {unset x}
+    set x 1
+    list [catch {vwait x(1)} msg] $msg
+} {1 {can't read "x(1)": variable isn't array}}
+test event-11.4 {Tcl_VwaitCmd procedure} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    after 10; update; # On Mac make sure update won't take long
+    after 100 {set x x-done}
+    after 200 {set y y-done}
+    after 300 {set z z-done}
+    after idle {set q q-done}
+    set x before
+    set y before
+    set z before
+    set q before
+    list [vwait y] $x $y $z $q
+} {{} x-done y-done before q-done}
+
+foreach i [after info] {
+    after cancel $i
+}
+
+test event-11.5 {Tcl_VwaitCmd procedure: round robin scheduling, 2 sources} {jim socket} {
+    set f1 [open test1 w]
+    proc accept {s args} {
+       puts $s foobar
+       close $s
+    }
+    set s1 [socket stream.server 5001]
+    after 200
+    set s2 [socket stream 127.0.0.1:5001]
+    close $s1
+    set x 0
+    set y 0
+    set z 0
+    fileevent $s2 writable { incr z }
+    vwait z
+    fileevent $f1 writable { incr x; if { $y == 3 } { set z done } }
+    fileevent $s2 writable { incr y; if { $x == 3 } { set z done } }
+    vwait z
+    close $f1
+    close $s2
+    file delete test1 test2
+    list $x $y $z
+} {3 3 done}
+
+# Note: This one doesn't really require socket, but mingw32 doesn't have socket and
+#       also doesn't allow file events (select) on non-sockets
+test event-11.6 {Tcl_VwaitCmd procedure: round robin scheduling, same source} {socket} {
+    file delete test1 test2
+    set f1 [open test1 w]
+    set f2 [open test2 w]
+    set x 0
+    set y 0
+    set z 0
+    update
+    fileevent $f1 writable { incr x; if { $y == 3 } { set z done } }
+    fileevent $f2 writable { incr y; if { $x == 3 } { set z done } }
+    vwait z
+    close $f1
+    close $f2
+    file delete test1 test2
+    list $x $y $z
+} {3 3 done}
+
+
+test event-12.1 {Tcl_UpdateCmd procedure} {
+    list [catch {update a b} msg] $msg
+} {1 {wrong # args: should be "update ?idletasks?"}}
+test event-12.3 {Tcl_UpdateCmd procedure} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    after 500 {set x after}
+    after idle {set y after}
+    after idle {set z "after, y = $y"}
+    set x before
+    set y before
+    set z before
+    update idletasks
+    list $x $y $z
+} {before after {after, y = after}}
+test event-12.4 {Tcl_UpdateCmd procedure} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    after 10; update; # On Mac make sure update won't take long
+    after 200 {set x x-done}
+    after 400 {set y y-done}
+    after idle {set z z-done}
+    set x before
+    set y before
+    set z before
+    after 300
+    update
+    list $x $y $z
+} {x-done before z-done}
+
+# cleanup
+foreach i [after info] {
+    after cancel $i
+}
+
+test event-13.1 "vwait/signal" signal {
+    signal handle ALRM
+    list [catch -signal {
+        alarm 0.1
+        # This is just to prevent the vwait from exiting immediately
+        stdin readable { format test }
+        vwait forever
+    } msg] $msg
+} {5 SIGALRM}
+
+testreport
diff --git a/jim/tests/exec.test b/jim/tests/exec.test
new file mode 100755 (executable)
index 0000000..50dc706
--- /dev/null
@@ -0,0 +1,423 @@
+# Commands covered:  exec
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: exec.test,v 1.8.2.1 2001/10/17 19:29:25 das Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd exec
+needs cmd flush
+needs cmd after eventloop
+
+# Sleep which supports fractions of a second
+if {[info commands sleep] eq {}} {
+    proc sleep {n} {
+       after [expr {int($n * 1000)}]
+    }
+}
+
+set f [open sleepx w]
+puts $f "#![info nameofexecutable]"
+puts $f {
+    set seconds [lindex $argv 0]
+    after [expr {int($seconds * 1000)}]
+}
+close $f
+#catch {exec chmod +x sleepx}
+set sleepx [list [info nameofexecutable] sleepx]
+
+# Basic operations.
+
+test exec-1.1 {basic exec operation} {
+    exec echo a b c
+} "a b c"
+test exec-1.2 {pipelining} {
+    exec echo a b c d | cat | cat
+} "a b c d"
+test exec-1.3 {pipelining} {
+    set a [exec echo a b c d | cat | wc]
+    list [scan $a "%d %d %d" b c d] $b $c
+} {3 1 4}
+set arg {12345678901234567890123456789012345678901234567890}
+set arg "$arg$arg$arg$arg$arg$arg"
+test exec-1.4 {long command lines} {
+    exec echo $arg
+} $arg
+set arg {}
+
+# I/O redirection: input from Tcl command.
+
+test exec-2.1 {redirecting input from immediate source} {
+    exec cat << "Sample text"
+} {Sample text}
+test exec-2.2 {redirecting input from immediate source} {
+    exec << "Sample text" cat | cat
+} {Sample text}
+test exec-2.3 {redirecting input from immediate source} {
+    exec cat << "Sample text" | cat
+} {Sample text}
+test exec-2.4 {redirecting input from immediate source} {
+    exec cat | cat << "Sample text"
+} {Sample text}
+test exec-2.5 {redirecting input from immediate source} {
+    exec cat "<<Joined to arrows"
+} {Joined to arrows}
+test exec-2.6 {redirecting input from immediate source, with UTF} {
+    # If this fails, it may give back:
+    # "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1"
+    # If it does, this means that the UTF -> external conversion did not 
+    # occur before writing out the temp file.
+    exec cat << "\uE9\uE0\uFC\uF1"
+} "\uE9\uE0\uFC\uF1"
+test exec-2.7 {redirecting input from immediate source with nulls} {
+    exec cat << "Sample\0text"
+} "Sample\0text"
+
+# I/O redirection: output to file.
+
+file delete gorp.file
+test exec-3.1 {redirecting output to file} {
+    exec echo "Some simple words" > gorp.file
+    exec cat gorp.file
+} "Some simple words"
+test exec-3.2 {redirecting output to file} {
+    exec echo "More simple words" | >gorp.file cat | cat
+    exec cat gorp.file
+} "More simple words"
+test exec-3.3 {redirecting output to file} {
+    exec > gorp.file echo "Different simple words" | cat | cat
+    exec cat gorp.file
+} "Different simple words"
+test exec-3.4 {redirecting output to file} {
+    exec echo "Some simple words" >gorp.file
+    exec cat gorp.file
+} "Some simple words"
+test exec-3.5 {redirecting output to file} {
+    exec echo "First line" >gorp.file
+    exec echo "Second line" >> gorp.file
+    exec cat gorp.file
+} "First line\nSecond line"
+test exec-3.6 {redirecting output to file} {
+    exec echo "First line" >gorp.file
+    exec echo "Second line" >>gorp.file
+    exec cat gorp.file
+} "First line\nSecond line"
+test exec-3.7 {redirecting output to file} {
+    set f [open gorp.file w]
+    puts $f "Line 1"
+    flush $f
+    exec echo "More text" >@ $f
+    exec echo >@$f "Even more"
+    puts $f "Line 3"
+    close $f
+    exec cat gorp.file
+} "Line 1\nMore text\nEven more\nLine 3"
+
+# I/O redirection: output and stderr to file.
+
+file delete gorp.file
+test exec-4.1 {redirecting output and stderr to file} {
+    exec echo "test output" >& gorp.file
+    exec cat gorp.file
+} "test output"
+test exec-4.2 {redirecting output and stderr to file} {
+    list [exec sh -c "echo foo bar 1>&2" >&gorp.file] \
+           [exec cat gorp.file]
+} {{} {foo bar}}
+test exec-4.3 {redirecting output and stderr to file} {
+    exec echo "first line" > gorp.file
+    list [exec sh -c "echo foo bar 1>&2" >>&gorp.file] \
+           [exec cat gorp.file]
+} "{} {first line\nfoo bar}"
+test exec-4.4 {redirecting output and stderr to file} {
+    set f [open gorp.file w]
+    puts $f "Line 1"
+    flush $f
+    exec echo "More text" >&@ $f
+    exec echo >&@$f "Even more"
+    puts $f "Line 3"
+    close $f
+    exec cat gorp.file
+} "Line 1\nMore text\nEven more\nLine 3"
+test exec-4.5 {redirecting output and stderr to file} {
+    set f [open gorp.file w]
+    puts $f "Line 1"
+    flush $f
+    exec >&@ $f sh -c "echo foo bar 1>&2"
+    exec >&@$f sh -c "echo xyzzy 1>&2"
+    puts $f "Line 3"
+    close $f
+    exec cat gorp.file
+} "Line 1\nfoo bar\nxyzzy\nLine 3"
+
+# I/O redirection: input from file.
+
+exec echo "Just a few thoughts" > gorp.file
+
+test exec-5.1 {redirecting input from file} {
+    exec cat < gorp.file
+} {Just a few thoughts}
+test exec-5.2 {redirecting input from file} {
+    exec cat | cat < gorp.file
+} {Just a few thoughts}
+test exec-5.3 {redirecting input from file} {
+    exec cat < gorp.file | cat
+} {Just a few thoughts}
+test exec-5.4 {redirecting input from file} {
+    exec < gorp.file cat | cat
+} {Just a few thoughts}
+test exec-5.5 {redirecting input from file} {
+    exec cat <gorp.file
+} {Just a few thoughts}
+test exec-5.6 {redirecting input from file} {
+    set f [open gorp.file r]
+    set result [exec cat <@ $f]
+    close $f
+    set result
+} {Just a few thoughts}
+test exec-5.7 {redirecting input from file} {
+    set f [open gorp.file r]
+    set result [exec <@$f cat]
+    close $f
+    set result
+} {Just a few thoughts}
+
+# I/O redirection: standard error through a pipeline.
+
+test exec-6.1 {redirecting stderr through a pipeline} {
+    exec sh -c "echo foo bar" |& cat
+} "foo bar"
+test exec-6.2 {redirecting stderr through a pipeline} {
+    exec sh -c "echo foo bar 1>&2" |& cat
+} "foo bar"
+test exec-6.3 {redirecting stderr through a pipeline} {
+    exec sh -c "echo foo bar 1>&2" \
+       |& cat |& cat
+} "foo bar"
+
+# I/O redirection: combinations.
+
+file delete gorp.file2
+test exec-7.1 {multiple I/O redirections} {
+    exec << "command input" > gorp.file2 cat < gorp.file
+    exec cat gorp.file2
+} {Just a few thoughts}
+test exec-7.2 {multiple I/O redirections} {
+    exec < gorp.file << "command input" cat
+} {command input}
+
+# Long input to command and output from command.
+
+set a "0123456789 xxxxxxxxx abcdefghi ABCDEFGHIJK\n"
+set a [concat $a $a $a $a]
+set a [concat $a $a $a $a]
+set a [concat $a $a $a $a]
+set a [concat $a $a $a $a]
+test exec-8.1 {long input and output} {
+    exec cat << $a
+} $a
+
+# More than 20 arguments to exec.
+
+test exec-8.1 {long input and output} {
+    exec echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23}
+
+# Commands that return errors.
+
+test exec-9.1 {commands returning errors} {
+    catch {exec gorp456}
+} {1}
+test exec-9.2 {commands returning errors} {
+    catch {exec echo foo | foo123} msg
+} {1}
+test exec-9.3 {commands returning errors} {
+    list [catch {exec {*}$sleepx 0.1 | false | {*}$sleepx 0.1} msg]
+} {1}
+test exec-9.4 {commands returning errors} jim {
+    list [catch {exec false | echo "foo bar"} msg] $msg
+} {1 {foo bar}}
+test exec-9.5 {commands returning errors} {
+    list [catch {exec gorp456 | echo a b c} msg]
+} {1}
+test exec-9.6 {commands returning errors} jim {
+    list [catch {exec sh -c "echo error msg 1>&2"} msg] $msg
+} {0 {error msg}}
+test exec-9.7 {commands returning errors} jim {
+    # Note: Use sleep here to ensure the order
+    list [catch {exec sh -c "echo error msg 1 1>&2" \
+                    | sh -c "sleep 0.1; echo error msg 2 1>&2"} msg] $msg
+} {0 {error msg 1
+error msg 2}}
+
+# Errors in executing the Tcl command, as opposed to errors in the
+# processes that are invoked.
+
+test exec-10.1 {errors in exec invocation} {
+    list [catch {exec} msg]
+} {1}
+test exec-10.2 {errors in exec invocation} {
+    list [catch {exec | cat} msg] $msg
+} {1 {illegal use of | or |& in command}}
+test exec-10.3 {errors in exec invocation} {
+    list [catch {exec cat |} msg] $msg
+} {1 {illegal use of | or |& in command}}
+test exec-10.4 {errors in exec invocation} {
+    list [catch {exec cat | | cat} msg] $msg
+} {1 {illegal use of | or |& in command}}
+test exec-10.5 {errors in exec invocation} {
+    list [catch {exec cat | |& cat} msg] $msg
+} {1 {illegal use of | or |& in command}}
+test exec-10.6 {errors in exec invocation} {
+    list [catch {exec cat |&} msg] $msg
+} {1 {illegal use of | or |& in command}}
+test exec-10.7 {errors in exec invocation} {
+    list [catch {exec cat <} msg] $msg
+} {1 {can't specify "<" as last word in command}}
+test exec-10.8 {errors in exec invocation} {
+    list [catch {exec cat >} msg] $msg
+} {1 {can't specify ">" as last word in command}}
+test exec-10.9 {errors in exec invocation} {
+    list [catch {exec cat <<} msg] $msg
+} {1 {can't specify "<<" as last word in command}}
+test exec-10.10 {errors in exec invocation} {
+    list [catch {exec cat >>} msg] $msg
+} {1 {can't specify ">>" as last word in command}}
+test exec-10.11 {errors in exec invocation} {
+    list [catch {exec cat >&} msg] $msg
+} {1 {can't specify ">&" as last word in command}}
+test exec-10.12 {errors in exec invocation} {
+    list [catch {exec cat >>&} msg] $msg
+} {1 {can't specify ">>&" as last word in command}}
+test exec-10.13 {errors in exec invocation} {
+    list [catch {exec cat >@} msg] $msg
+} {1 {can't specify ">@" as last word in command}}
+test exec-10.14 {errors in exec invocation} {
+    list [catch {exec cat <@} msg] $msg
+} {1 {can't specify "<@" as last word in command}}
+test exec-10.15 {errors in exec invocation} {
+    list [catch {exec cat < a/b/c} msg] [string tolower $msg]
+} {1 {couldn't read file "a/b/c": no such file or directory}}
+test exec-10.16 {errors in exec invocation} {
+    list [catch {exec cat << foo > a/b/c} msg] [string tolower $msg]
+} {1 {couldn't write file "a/b/c": no such file or directory}}
+test exec-10.17 {errors in exec invocation} {
+    list [catch {exec cat << foo > a/b/c} msg] [string tolower $msg]
+} {1 {couldn't write file "a/b/c": no such file or directory}}
+set f [open gorp.file w]
+test exec-10.18 {errors in exec invocation} {
+    list [catch {exec cat <<test <@ $f} msg]
+} 1
+close $f
+set f [open gorp.file r]
+test exec-10.19 {errors in exec invocation} {
+    list [catch {exec cat <<test >@ $f} msg]
+} 1
+close $f
+
+# Commands in background.
+
+test exec-11.1 {commands in background} {
+    set x [lindex [time {exec {*}$sleepx 0.2 &}] 0]
+    expr $x<1000000
+} 1
+test exec-11.2 {commands in background} {
+    list [catch {exec echo a &b} msg] $msg
+} {0 {a &b}}
+test exec-11.3 {commands in background} {
+    llength [exec {*}$sleepx 0.1 &]
+} 1
+test exec-11.4 {commands in background} {
+    llength [exec {*}$sleepx 0.1 | {*}$sleepx 0.1 | {*}$sleepx 0.1 &]
+} 3
+
+# Make sure that background commands are properly reaped when
+# they eventually die.
+
+exec {*}$sleepx 0.3
+
+test exec-12.1 {reaping background processes} -body {
+    for {set i 0} {$i < 20} {incr i} {
+               exec echo foo > exec.tmp1 &
+    }
+    exec {*}$sleepx 0.1
+    catch {exec ps | fgrep "echo foo" | fgrep -v fgrep | wc} msg
+    lindex $msg 0
+} -cleanup {
+    file delete exec.tmp1
+} -result 0
+
+# Redirecting standard error separately from standard output
+
+test exec-15.1 {standard error redirection} {
+    exec echo "First line" > gorp.file
+    list [exec sh -c "echo foo bar 1>&2" 2> gorp.file] \
+           [exec cat gorp.file]
+} {{} {foo bar}}
+test exec-15.2 {standard error redirection} {
+    list [exec sh -c "echo foo bar 1>&2" \
+               | echo biz baz >gorp.file 2> gorp.file2] \
+           [exec cat gorp.file] \
+           [exec cat gorp.file2]
+} {{} {biz baz} {foo bar}}
+test exec-15.3 {standard error redirection} {
+    list [exec sh -c "echo foo bar 1>&2" \
+               | echo biz baz 2>gorp.file > gorp.file2] \
+           [exec cat gorp.file] \
+           [exec cat gorp.file2]
+} {{} {foo bar} {biz baz}}
+test exec-15.4 {standard error redirection} {
+    set f [open gorp.file w]
+    puts $f "Line 1"
+    flush $f
+    exec sh -c "echo foo bar 1>&2" 2>@ $f
+    puts $f "Line 3"
+    close $f
+    exec cat gorp.file
+} {Line 1
+foo bar
+Line 3}
+test exec-15.5 {standard error redirection} {
+    exec echo "First line" > gorp.file
+    exec sh -c "echo foo bar 1>&2" 2>> gorp.file
+    exec cat gorp.file
+} {First line
+foo bar}
+test exec-15.6 {standard error redirection} {
+    exec sh -c "echo foo bar 1>&2" > gorp.file2 2> gorp.file \
+           >& gorp.file 2> gorp.file2 | echo biz baz
+    list [exec cat gorp.file] [exec cat gorp.file2]
+} {{biz baz} {foo bar}}
+test exec-15.7 {combine standard output/standard error} -body {
+    exec sh -c "echo foo bar 1>&2" > gorp.file 2>@1
+    exec cat gorp.file
+} -cleanup {
+    file delete gorp.file gorp.file2
+} -result {foo bar}
+
+test exec-16.1 {flush output before exec} -body {
+    set f [open gorp.file w]
+    puts $f "First line"
+    exec echo "Second line" >@ $f
+    puts $f "Third line"
+    close $f
+    exec cat gorp.file
+} -cleanup {
+    file delete gorp.file
+} -result {First line
+Second line
+Third line}
+
+file delete sleepx
+
+testreport
diff --git a/jim/tests/exec2.test b/jim/tests/exec2.test
new file mode 100755 (executable)
index 0000000..e43bba0
--- /dev/null
@@ -0,0 +1,47 @@
+# These tests are design especially for the vfork() implementation
+# of exec where sh -c must be used and thus we must take extra care
+# in quoting arguments to exec.
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd exec
+
+set d \"
+set s '
+set b \\
+
+array set saveenv [array get env]
+
+test exec2-1.1 "Quoting - Result" {
+       exec echo ${d}double quoted${d} ${s}single quoted${s} ${b}backslash quoted${b}
+} "\"double\ quoted\"\ 'single quoted'\ \\backslash\ quoted\\"
+
+test exec2-1.2 "Quoting - Word Grouping" {
+       string trim [exec echo ${d}double quoted${d} ${s}single quoted${s} ${b}backslash quoted${b} | wc -w]
+} {6}
+
+test exec2-2.1 "Add to exec environment" {
+       set env(TESTENV) "the value"
+       exec printenv | sed -n -e /^TESTENV=/p
+} {TESTENV=the value}
+
+test exec2-2.2 "Remove from exec environment" {
+       set env(TESTENV2) "new value"
+       unset env(TESTENV)
+       exec printenv | sed -n -e /^TESTENV=/p
+} {}
+
+
+test exec2-2.3 "Remove all exec environment" {
+       array unset env *
+       exec printenv | sed -n -e /^TESTENV2=/p
+} {}
+
+test exec2-2.4 "Remove all env var" {
+       unset -nocomplain env
+       exec printenv | sed -n -e /^TESTENV2=/p
+} {}
+
+array set env [array get saveenv]
+
+testreport
diff --git a/jim/tests/exists.test b/jim/tests/exists.test
new file mode 100755 (executable)
index 0000000..11e8781
--- /dev/null
@@ -0,0 +1,79 @@
+source [file dirname [info script]]/testing.tcl
+
+needs cmd exists
+testConstraint lambda [expr {[info commands lambda] ne {}}]
+
+test exists-1.1 "Exists var" {
+       set a 1
+       exists a
+} 1
+
+test exists-1.1 "Exists var" {
+       unset -nocomplain b
+       exists b
+} 0
+
+test exists-1.1 "Exists -var" {
+       exists -var a
+} 1
+
+test exists-1.1 "Exists -var" {
+       exists -var b
+} 0
+
+test exists-1.1 "Exists in proc" {
+       proc a {name} { exists $name }
+       a ::a
+} 1
+
+test exists-1.1 "Exists in proc" {
+       a ::b
+} 0
+
+test exists-1.1 "Exists in proc" {
+       a name
+} 1
+
+test exists-1.1 "Exists in proc" {
+       a none
+} 0
+
+test exists-1.1 "Exists -proc" {
+       exists -proc a
+} 1
+
+test exists-1.1 "Exists -proc" {
+       exists -proc bogus
+} 0
+
+test exists-1.1 "Exists -proc" {
+       exists -proc info
+} 0
+
+test exists-1.1 "Exists -command" {
+       exists -command a
+} 1
+
+test exists-1.1 "Exists -command" {
+       exists -command info
+} 1
+
+test exists-1.1 "Exists -command" {
+       exists -command bogus
+} 0
+
+test exists-1.1 "Exists local lambda after exit" lambda {
+       proc a {} {
+               local lambda {} {dummy}
+       }
+       exists -proc [a]
+} 0
+
+test exists-1.1 "Exists local lambda" lambda {
+       proc a {} {
+               exists -proc [local lambda {} {dummy}]
+       }
+       a
+} 1
+
+testreport
diff --git a/jim/tests/exitpackage.tcl b/jim/tests/exitpackage.tcl
new file mode 100755 (executable)
index 0000000..c292557
--- /dev/null
@@ -0,0 +1,3 @@
+# This package just exits
+
+exit 1
diff --git a/jim/tests/expand.test b/jim/tests/expand.test
new file mode 100755 (executable)
index 0000000..2c7023a
--- /dev/null
@@ -0,0 +1,27 @@
+source [file dirname [info script]]/testing.tcl
+
+test expand-1.1 "Basic tests" {
+       set a {1 2 3}
+       set b {4 5 6}
+       lappend a {*}$b
+} {1 2 3 4 5 6}
+
+test expand-1.2 "Basic tests" jim {
+       set a {1 2 3}
+       set b {4 5 6}
+       lappend a {expand}$b
+} {1 2 3 4 5 6}
+
+test expand-1.3 "Basic tests" {
+       set a {1 2 3}
+       set b {4 5 6}
+       lappend a *$b
+} {1 2 3 {*4 5 6}}
+
+test expand-1.4 "Basic tests" {
+       set a {1 2 3}
+       set b {4 5 6}
+       lappend a expand$b
+} {1 2 3 {expand4 5 6}}
+
+testreport
diff --git a/jim/tests/expr-base.test b/jim/tests/expr-base.test
new file mode 100755 (executable)
index 0000000..5c9e1da
--- /dev/null
@@ -0,0 +1,39 @@
+source [file dirname [info script]]/testing.tcl
+
+# Test number detection
+set good_testcases {
+       0                       0
+       1                       1
+       8                       8
+       00                      0
+       07                      7
+       08                      8
+       0x5                     5
+       0x0                     0
+       0x00            0
+       -0x5            -5
+       0b111           7
+       -0b111          -7
+       -0B101          -5
+       0o7                     7
+}
+
+set i 0
+foreach {str exp} $good_testcases {
+       test expr-base-1.[incr i] "expr conversion" [list expr [list $str]] $exp
+}
+
+set bad_testcases {
+       {0x + 1}
+       x
+       0xx5
+       0x-5
+       {0x 5}
+       {0o8 + 1}
+}
+
+set i 0
+foreach str $bad_testcases {
+       test expr-base-2.[incr i] "expr conversion failure" -returnCodes error -body [list expr $str] -match glob -result "*"
+}
+testreport
diff --git a/jim/tests/expr-new.test b/jim/tests/expr-new.test
new file mode 100755 (executable)
index 0000000..e3c4378
--- /dev/null
@@ -0,0 +1,582 @@
+# Commands covered: expr
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1996-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: expr.test,v 1.9 2000/04/10 17:18:59 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+# procedures used below
+
+proc put_hello_char {c} {
+    global a
+    append a [format %c $c]
+    return $c
+}
+proc hello_world {} {
+    global a
+    set a ""
+    set L1 [set l0 [set h_1 [set q 0]]]
+    for {put_hello_char [expr [put_hello_char [expr [set h 7]*10+2]]+29]} {$l0?[put_hello_char $l0]
+        :!$h_1} {put_hello_char $ll;expr {$L1==2?[set ll [expr 32+0-0+[set bar 0]]]:0}} {expr {[incr L1]==[expr 1+([string length "abc"]-[string length "abc"])]
+        ?[set ll [set l0 [expr 54<<1]]]:$ll==108&&$L1<3?
+        [incr ll [expr 1|1<<1]; set ll $ll; set ll $ll; set ll $ll; set ll $ll; set l0 [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]; set l0; set l0 $l0; set l0; set l0]:$L1==4&&$ll==32?[set ll [expr 19+$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+[set foo [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]]]]
+        :[set q [expr $q-$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]};expr {$L1==5?[incr ll -8; set ll $ll; set ll]:$q&&$h1&&1};expr {$L1==4+2
+        ?[incr ll 3]:[expr ([string length "abc"]-[string length "abc"])+1]};expr {$ll==($h<<4)+2+0&&$L1!=6?[incr ll -6]:[set h1 [expr 100+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]}
+        expr {$L1!=1<<3?[incr q [expr ([string length "abc"]-[string length "abc"])-1]]:[set h_1 [set ll $h1]]}
+    }
+    set a
+}
+
+proc 12days {a b c} {
+    global xxx
+    expr {1<$a?[expr {$a<3?[12days -79 -13 [string range $c [12days -87 \
+       [expr 1-$b] [string range $c [12days -86 0 [string range $c 1 end]] \
+       end]] end]]:1};expr {$a<$b?[12days [expr $a+1] $b $c]:3};expr {[12days \
+       -94 [expr $a-27] $c]&&$a==2?$b<13?[12days 2 [expr $b+1] "%s %d %d\n"]:9
+       :16}]:$a<0?$a<-72?[12days $b $a "@n'+,#'/*\{\}w+/w#cdnr/+,\{\}r/*de\}+,/*\{*+,/w\{%+,/w#q#n+,/#\{l+,/n\{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,\}\{w+K w'K:'+\}e#';dq#'l q#'+d'K#!/+k#;q#'r\}eKK#\}w'r\}eKK\{nl\]'/#;#q#n')\{)#\}w')\{)\{nl\]'/+#n';d\}rw' i;# )\{nl\]!/n\{n#'; r\{#w'r nc\{nl\]'/#\{l,+'K \{rw' iK\{;\[\{nl\]'/w#q#n'wk nw' iwk\{KK\{nl\]!/w\{%'l##w#' i; :\{nl\]'/*\{q#'ld;r'\}\{nlwb!/*de\}'c ;;\{nl'-\{\}rw\]'/+,\}##'*\}#nc,',#nw\]'/+kd'+e\}+;#'rdq#w! nr'/ ') \}+\}\{rl#'\{n' ')# \}'+\}##(!!/"]
+       :$a<-50?[string compare [format %c $b] [string index $c 0]]==0?[append \
+       xxx [string index $c 31];scan [string index $c 31] %c x;set x]
+       :[12days -65 $b [string range $c 1 end]]:[12days [expr ([string compare \
+       [string index $c 0] "/"]==0)+$a] $b [string range $c 1 end]]:0<$a
+       ?[12days 2 2 "%s"]:[string compare [string index $c 0] "/"]==0||
+       [12days 0 [12days -61 [scan [string index $c 0] %c x; set x] \
+       "!ek;dc i@bK'(q)-\[w\]*%n+r3#l,\{\}:\nuwloca-O;m .vpbks,fxntdCeghiry"] \
+       [string range $c 1 end]]}
+}
+proc do_twelve_days {} {
+    global xxx
+    set xxx ""
+    12days 1 1 1
+    string length $xxx
+}
+
+# start of tests
+
+catch {unset a b i x}
+
+test expr-1.1 {TclCompileExprCmd: no expression} {
+    list [catch {expr  } msg]
+} {1}
+test expr-1.2 {TclCompileExprCmd: one expression word} {
+    expr -25
+} -25
+test expr-1.3 {TclCompileExprCmd: two expression words} {
+    expr -8.2   -6
+} -14.2
+test expr-1.4 {TclCompileExprCmd: five expression words} {
+    expr 20 - 5 +10 -7
+} 18
+test expr-1.5 {TclCompileExprCmd: quoted expression word} {
+    expr "0005"
+} 5
+test expr-1.6 {TclCompileExprCmd: quoted expression word} {
+    catch {expr "0005"zxy} msg
+} {1}
+test expr-1.7 {TclCompileExprCmd: expression word in braces} {
+    expr {-0005}
+} -5
+# XXX: I believe that this ought to return a string, thus -0x1234
+#test expr-1.8 {TclCompileExprCmd: expression word in braces} {
+#    expr {{-0x1234}}
+#} -4660
+test expr-1.9 {TclCompileExprCmd: expression word in braces} {
+    catch {expr {-0005}foo} msg
+} {1}
+test expr-1.10 {TclCompileExprCmd: other expression word in braces} {
+    expr 4*[llength "6 2"]
+} 8
+test expr-1.11 {TclCompileExprCmd: expression word terminated by ;} {
+    expr 4*[llength "6 2"];
+} 8
+test expr-1.12 {TclCompileExprCmd: inlined expr (in "catch") inside other catch} {
+    set a xxx
+    catch {
+       # Might not be a number
+       set a [expr 10*$a]
+    }
+} 1
+test expr-1.13 {TclCompileExprCmd: second level of substitutions in expr not in braces with single var reference} {
+    set a xxx
+    set x 27;  set bool {$x};  if $bool {set a foo}
+    set a
+} foo
+test expr-1.14 {TclCompileExprCmd: second level of substitutions in expr with comparison as top-level operator} {
+    set a xxx
+    set x 2;  set b {$x};  set a [expr $b == 2]
+    set a
+} 1
+
+test expr-2.1 {TclCompileExpr: are builtin functions registered?} {
+    expr double(5*[llength "6 2"])
+} 10.0
+test expr-2.2 {TclCompileExpr: error in expr} {
+    catch {expr 2//3} msg
+} {1}
+test expr-2.3 {TclCompileExpr: junk after legal expr} {
+    catch {expr 7*[llength "a b"]foo} msg
+} {1}
+test expr-2.4 {TclCompileExpr: numeric expr string rep == formatted int rep} {
+    expr {0001}
+} 1
+
+test expr-3.1 {CompileCondExpr: just lor expr} {expr 3||0} 1
+test expr-3.2 {CompileCondExpr: error in lor expr} {
+    catch {expr x||3} msg
+} {1}
+test expr-3.3 {CompileCondExpr: test true arm} {expr 3>2?44:66} 44
+test expr-3.4 {CompileCondExpr: error compiling true arm} {
+    catch {expr 3>2?2//3:66} msg
+} {1}
+test expr-3.5 {CompileCondExpr: test false arm} {expr 2>3?44:66} 66
+test expr-3.6 {CompileCondExpr: error compiling false arm} {
+    catch {expr 2>3?44:2//3} msg
+} {1}
+if {0} {
+test expr-3.7 {CompileCondExpr: long arms & nested cond exprs} {
+    puts "Note: doing test expr-3.7 which can take several minutes to run"
+    hello_world
+} {Hello world}
+catch {unset xxx}
+test expr-3.8 {CompileCondExpr: long arms & nested cond exprs} {
+    puts "Note: doing test expr-3.8 which can take several minutes to run"
+    do_twelve_days
+} 2358
+catch {unset xxx}
+}
+
+test expr-4.1 {CompileLorExpr: just land expr} {expr 1.3&&3.3} 1
+test expr-4.2 {CompileLorExpr: error in land expr} {
+    catch {expr x&&3} msg
+} {1}
+test expr-4.3 {CompileLorExpr: simple lor exprs} {expr 0||1.0} 1
+test expr-4.4 {CompileLorExpr: simple lor exprs} {expr 3.0||0.0} 1
+test expr-4.5 {CompileLorExpr: simple lor exprs} {expr 0||0||1} 1
+test expr-4.6 {CompileLorExpr: error compiling lor arm} {
+    catch {expr 2//3||4.0} msg
+} {1}
+test expr-4.7 {CompileLorExpr: error compiling lor arm} {
+    catch {expr 1.3||2//3} msg
+} {1}
+test expr-4.8 {CompileLorExpr: error compiling lor arms} {
+    list [catch {expr {"a"||"b"}} msg]
+} {1}
+test expr-4.9 {CompileLorExpr: long lor arm} {
+    set a "abcdefghijkl"
+    set i 7
+    expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]}
+} 1
+
+test expr-5.1 {CompileLandExpr: just bitor expr} {expr 7|0x13} 23
+test expr-5.2 {CompileLandExpr: error in bitor expr} {
+    catch {expr x|3} msg
+} {1}
+test expr-5.3 {CompileLandExpr: simple land exprs} {expr 0&&1.0} 0
+test expr-5.4 {CompileLandExpr: simple land exprs} {expr 0&&0} 0
+test expr-5.5 {CompileLandExpr: simple land exprs} {expr 3.0&&1.2} 1
+test expr-5.6 {CompileLandExpr: simple land exprs} {expr 1&&1&&2} 1
+test expr-5.7 {CompileLandExpr: error compiling land arm} {
+    catch {expr 2//3&&4.0} msg
+} {1}
+test expr-5.8 {CompileLandExpr: error compiling land arm} {
+    catch {expr 1.3&&2//3} msg
+} {1}
+test expr-5.9 {CompileLandExpr: error compiling land arm} {
+    list [catch {expr {"a"&&"b"}} msg]
+} {1}
+test expr-5.10 {CompileLandExpr: long land arms} {
+    set a "abcdefghijkl"
+    set i 7
+    expr {[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]}
+} 1
+
+test expr-6.1 {CompileBitXorExpr: just bitand expr} {expr 7&0x13} 3
+test expr-6.2 {CompileBitXorExpr: error in bitand expr} {
+    catch {expr x|3} msg
+} {1}
+test expr-6.3 {CompileBitXorExpr: simple bitxor exprs} {expr 7^0x13} 20
+test expr-6.4 {CompileBitXorExpr: simple bitxor exprs} {expr 3^0x10} 19
+test expr-6.5 {CompileBitXorExpr: simple bitxor exprs} {expr 0^7} 7
+test expr-6.6 {CompileBitXorExpr: simple bitxor exprs} {expr -1^7} -8
+test expr-6.7 {CompileBitXorExpr: error compiling bitxor arm} {
+    catch {expr 2//3|6} msg
+} {1}
+test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} {
+    catch {expr 2^x} msg
+} {1}
+test expr-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
+    list [catch {expr {24.0^3}} msg]
+} {1}
+test expr-6.10 {CompileBitXorExpr: runtime error in bitxor arm} {
+    list [catch {expr {"a"^"b"}} msg]
+} {1}
+
+test expr-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
+test expr-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
+test expr-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
+test expr-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
+test expr-7.5 {CompileBitAndExpr: error in equality expr} {
+    catch {expr x==3} msg
+} {1}
+test expr-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
+test expr-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
+test expr-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
+test expr-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
+test expr-7.10 {CompileBitAndExpr: error compiling bitand arm} {
+    catch {expr 2//3&6} msg
+} {1}
+test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} {
+    catch {expr 2&x} msg
+} {1}
+test expr-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
+    list [catch {expr {24.0&3}} msg]
+} {1}
+test expr-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
+    list [catch {expr {"a"&"b"}} msg]
+} {1}
+
+test expr-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
+test expr-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1
+test expr-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1
+test expr-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0
+test expr-8.5 {CompileEqualityExpr: error in relational expr} {
+    catch {expr x>3} msg
+} {1}
+test expr-8.6 {CompileEqualityExpr: simple equality exprs} {expr 7==0x13} 0
+test expr-8.7 {CompileEqualityExpr: simple equality exprs} {expr -0xf2!=0x53} 1
+test expr-8.8 {CompileEqualityExpr: simple equality exprs} {expr {"12398712938788234-1298379" != ""}} 1
+test expr-8.9 {CompileEqualityExpr: simple equality exprs} {expr -1!="abc"} 1
+test expr-8.10 {CompileEqualityExpr: error compiling equality arm} {
+    catch {expr 2//3==6} msg
+} {1}
+test expr-8.11 {CompileEqualityExpr: error compiling equality arm} {
+    catch {expr 2!=x} msg
+} {1}
+
+
+test expr-9.1 {CompileRelationalExpr: just shift expr} {expr 3<<2} 12
+test expr-9.2 {CompileRelationalExpr: just shift expr} {expr 0xff>>2} 63
+test expr-9.3 {CompileRelationalExpr: just shift expr} {expr -1>>2} -1
+test expr-9.4 {CompileRelationalExpr: just shift expr} {expr {1<<3}} 8
+
+# The following test is different for 32-bit versus 64-bit
+# architectures because LONG_MIN is different
+
+if {0x80000000 > 0} {
+    test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN (64bit)} jim {
+       expr {1<<63}
+    } -9223372036854775808
+} else {
+    test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN (32bit)} jim {
+       expr {1<<31}
+    } -2147483648
+}
+test expr-9.6 {CompileRelationalExpr: error in shift expr} {
+    catch {expr x>>3} msg
+} {1}
+test expr-9.7 {CompileRelationalExpr: simple relational exprs} {expr 0xff>=+0x3} 1
+test expr-9.8 {CompileRelationalExpr: simple relational exprs} {expr -0xf2<0x3} 1
+test expr-9.9 {CompileRelationalExpr: error compiling relational arm} {
+    catch {expr 2//3>6} msg
+} {1}
+test expr-9.10 {CompileRelationalExpr: error compiling relational arm} {
+    catch {expr 2<x} msg
+} {1}
+
+test expr-10.1 {CompileShiftExpr: just add expr} {expr 4+-2} 2
+test expr-10.2 {CompileShiftExpr: just add expr} {expr 0xff-2} 253
+test expr-10.3 {CompileShiftExpr: just add expr} {expr -1--2} 1
+test expr-10.4 {CompileShiftExpr: just add expr} {expr 1-0123} -122
+test expr-10.5 {CompileShiftExpr: error in add expr} {
+    catch {expr x+3} msg
+} {1}
+test expr-10.6 {CompileShiftExpr: simple shift exprs} {expr 0xff>>0x3} 31
+test expr-10.7 {CompileShiftExpr: simple shift exprs} {expr -0xf2<<0x3} -1936
+test expr-10.8 {CompileShiftExpr: error compiling shift arm} {
+    catch {expr 2//3>>6} msg
+} {1}
+test expr-10.9 {CompileShiftExpr: error compiling shift arm} {
+    catch {expr 2<<x} msg
+} {1}
+test expr-10.10 {CompileShiftExpr: runtime error} {
+    list [catch {expr {24.0>>43}} msg]
+} {1}
+test expr-10.11 {CompileShiftExpr: runtime error} {
+    list [catch {expr {"a"<<"b"}} msg]
+} {1}
+
+test expr-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
+test expr-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
+test expr-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
+test expr-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0123} 19
+test expr-11.5 {CompileAddExpr: error in multiply expr} {
+    catch {expr x*3} msg
+} {1}
+test expr-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
+test expr-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
+test expr-11.8 {CompileAddExpr: error compiling add arm} {
+    catch {expr 2//3+6} msg
+} {1}
+test expr-11.9 {CompileAddExpr: error compiling add arm} {
+    catch {expr 2-x} msg
+} {1}
+test expr-11.10 {CompileAddExpr: runtime error} {
+    list [catch {expr {24.0+"xx"}} msg]
+} {1}
+test expr-11.11 {CompileAddExpr: runtime error} {
+    list [catch {expr {"a"-"b"}} msg]
+} {1}
+test expr-11.12 {CompileAddExpr: runtime error} {
+    list [catch {expr {3/0}} msg]
+} {1}
+test expr-11.13 {CompileAddExpr: divide by zero} {
+    expr {2.3/0.0}
+} {Inf}
+test expr-11.14 {CompileAddExpr: divide by zero} {
+    expr {-2.3/0.0}
+} {-Inf}
+
+test expr-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5
+test expr-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5
+test expr-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0
+test expr-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936
+test expr-12.5 {CompileMultiplyExpr: error in unary expr} {
+    catch {expr ~x} msg
+} {1}
+test expr-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765
+test expr-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2
+test expr-12.8 {CompileMultiplyExpr: error compiling multiply arm} {
+    catch {expr 2*3%%6} msg
+} {1}
+test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} {
+    catch {expr 2*x} msg
+} {1}
+test expr-12.10 {CompileMultiplyExpr: runtime error} {
+    list [catch {expr {24.0*"xx"}} msg]
+} {1}
+test expr-12.11 {CompileMultiplyExpr: runtime error} {
+    list [catch {expr {"a"/"b"}} msg]
+} {1}
+
+test expr-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
+test expr-13.2 {CompileUnaryExpr: unary exprs} {expr +000123} 123
+test expr-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
+test expr-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
+test expr-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
+test expr-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
+test expr-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
+test expr-13.8 {CompileUnaryExpr: error compiling unary expr} {
+    catch {expr ~x} msg
+} {1}
+test expr-13.9 {CompileUnaryExpr: error compiling unary expr} {
+    catch {expr !1.x} msg
+} {1}
+test expr-13.10 {CompileUnaryExpr: runtime error} {
+    list [catch {expr {~"xx"}} msg]
+} {1}
+test expr-13.11 {CompileUnaryExpr: runtime error} {
+    list [catch {expr ~4.0} msg]
+} {1}
+test expr-13.12 {CompileUnaryExpr: just primary expr} {expr 0x123} 291
+test expr-13.13 {CompileUnaryExpr: just primary expr} {
+    set a 27
+    expr $a
+} 27
+test expr-13.14 {CompileUnaryExpr: just primary expr} {
+    expr double(27)
+} 27.0
+test expr-13.15 {CompileUnaryExpr: just primary expr} {expr "123"} 123
+test expr-13.16 {CompileUnaryExpr: error in primary expr} {
+    catch {expr [set]} msg
+} {1}
+test expr-14.1 {CompilePrimaryExpr: literal primary} {expr 1} 1
+test expr-14.2 {CompilePrimaryExpr: literal primary} {expr 123} 123
+test expr-14.3 {CompilePrimaryExpr: literal primary} {expr 0xff} 255
+test expr-14.4 {CompilePrimaryExpr: literal primary} {expr 00010} 10
+test expr-14.5 {CompilePrimaryExpr: literal primary} {expr 62.0} 62.0
+test expr-14.6 {CompilePrimaryExpr: literal primary} {
+    expr 3.1400000
+} 3.14
+test expr-14.7 {CompilePrimaryExpr: literal primary} {expr {{abcde}<{abcdef}}} 1
+test expr-14.8 {CompilePrimaryExpr: literal primary} {expr {{abc\
+def} < {abcdef}}} 1
+test expr-14.9 {CompilePrimaryExpr: literal primary} {expr {{abc\tde} > {abc\tdef}}} 0
+test expr-14.10 {CompilePrimaryExpr: literal primary} {expr {{123}}} 123
+test expr-14.11 {CompilePrimaryExpr: var reference primary} {
+    set i 789
+    list [expr {$i}] [expr $i]
+} {789 789}
+test expr-14.12 {CompilePrimaryExpr: var reference primary} {
+    set i {789}    ;# test expr's aggressive conversion to numeric semantics
+    list [expr {$i}] [expr $i]
+} {789 789}
+test expr-14.13 {CompilePrimaryExpr: var reference primary} {
+    catch {unset a}
+    set a(foo) foo
+    set a(bar) bar
+    set a(123) 123
+    set result ""
+    lappend result [expr $a(123)] [expr {$a(bar)<$a(foo)}]
+    catch {unset a}
+    set result
+} {123 1}
+test expr-14.14 {CompilePrimaryExpr: var reference primary} {
+    set i 123    ;# test "$var.0" floating point conversion hack
+    list [expr $i] [expr $i.0] [expr $i.0/12.0]
+} {123 123.0 10.25}
+test expr-14.15 {CompilePrimaryExpr: var reference primary} {
+    set i 123
+    catch {expr $i.2} msg
+    set msg
+} 123.2
+test expr-14.16 {CompilePrimaryExpr: error compiling var reference primary} {
+    catch {expr {$a(foo}} msg
+} {1}
+test expr-14.18 {CompilePrimaryExpr: quoted string primary} {
+    expr "21"
+} 21
+test expr-14.19 {CompilePrimaryExpr: quoted string primary} {
+    set i 123
+    set x 456
+    expr "$i+$x"
+} 579
+test expr-14.20 {CompilePrimaryExpr: quoted string primary} {
+    set i 3
+    set x 6
+    expr 2+"$i.$x"
+} 5.6
+test expr-14.21 {CompilePrimaryExpr: error in quoted string primary} {
+    catch {expr "[set]"} msg
+} {1}
+test expr-14.22 {CompilePrimaryExpr: subcommand primary} {
+    expr {[set i 123; set i]}
+} 123
+test expr-14.23 {CompilePrimaryExpr: error in subcommand primary} {
+    catch {expr {[set]}} msg
+} {1}
+test expr-14.24 {CompilePrimaryExpr: error in subcommand primary} {
+    catch {expr {[set blah}} msg
+} {1}
+test expr-14.28 {CompilePrimaryExpr: subexpression primary} {
+    expr 2+(3*4)
+} 14
+test expr-14.29 {CompilePrimaryExpr: error in subexpression primary} {
+    catch {expr 2+(3*[set])} msg
+} {1}
+test expr-14.30 {CompilePrimaryExpr: missing paren in subexpression primary} {
+    catch {expr 2+(3*(4+5)} msg
+} {1}
+test expr-14.31 {CompilePrimaryExpr: just var ref in subexpression primary} {
+    set i "5+10"
+    list "[expr $i] == 15" "[expr ($i)] == 15" "[eval expr ($i)] == 15"
+} {{15 == 15} {15 == 15} {15 == 15}}
+test expr-14.32 {CompilePrimaryExpr: unexpected token} {
+    catch {expr @} msg
+} {1}
+
+test expr-15.2 {CompileMathFuncCall: unknown math function} {
+    catch {expr whazzathuh(1)} msg
+} {1}
+
+test expr-16.1 {GetToken: checks whether integer token starting with "0x" (e.g., "0x$") is invalid} {
+    catch {unset a}
+    set a(VALUE) ff15
+    set i 123
+    if {[expr 0x$a(VALUE)] & 16} {
+        set i {}
+    }
+    set i
+} {}
+test expr-16.2 {GetToken: check for string literal in braces} {
+    expr {{1}}
+} {1}
+
+# Check "expr" and computed command names.
+
+test expr-17.1 {expr and computed command names} {
+    set i 0
+    set z expr
+    $z 1+2
+} 3
+
+# Check correct conversion of operands to numbers: If the string looks like
+# an integer, convert to integer. Otherwise, if the string looks like a
+# double, convert to double.
+
+test expr-18.1 {expr and conversion of operands to numbers} {
+    set x [lindex 11 0]
+    catch {expr int($x)}
+    expr {$x}
+} 11
+test expr-18.2 {whitespace strings should not be == 0 (buggy strtod)} {
+    expr {" "}
+} { }
+
+# Check "expr" and interpreter result object resetting before appending
+# an error msg during evaluation of exprs not in {}s
+
+test expr-19.1 {expr and interpreter result object resetting} {
+    proc p {} {
+        set t  10.0
+        set x  2.0
+        set dx 0.2
+        set f  {$dx-$x/10}
+        set g  {-$x/5}
+        set center 1.0
+        set x  [expr $x-$center]
+        set dx [expr $dx+$g]
+        set x  [expr $x+$f+$center]
+        set x  [expr $x+$f+$center]
+        set y  [expr round($x)]
+    }
+    p
+} 3
+
+catch {unset a}
+
+# Test for incorrect "double evaluation" semantics
+
+#XXX: Jim doesn't care about missing braces
+#test expr-20.1 {wrong brace matching} {
+#    catch {unset l}
+#    catch {unset r}
+#    catch {unset q}
+#    catch {unset cmd}
+#    catch {unset a}
+#    set l "\{"; set r "\}"; set q "\""
+#    set cmd "expr $l$q|$q == $q$r$q$r"
+#    catch $cmd a
+#} {1}
+test expr-20.3 {broken substitution of integer digits} {
+    # fails with 8.0.x, but not 8.1b2
+    list [set a 000; expr 0x1$a] [set a 1; expr ${a}000]
+} {4096 1000}
+test expr-20.4 {proper double evaluation compilation, error case} {
+    catch {unset a}; # make sure $a doesn't exist
+    list [catch {expr 1?{$a}:0} msg]
+} {1}
+test expr-20.5 {proper double evaluation compilation, working case} {
+    set a yellow
+    expr 1?{$a}:0
+} yellow
+test expr-20.6 {handling of compile error in trial compile} {
+    list [catch {expr + {[incr]}} msg]
+} {1}
+test expr-20.7 {handling of compile error in runtime case} {
+    list [catch {expr + {[error foo]}} msg]
+} {1}
+
+# cleanup
+if {[info exists a]} {
+    unset a
+}
+
+testreport
diff --git a/jim/tests/expr-old.test b/jim/tests/expr-old.test
new file mode 100755 (executable)
index 0000000..b1d722d
--- /dev/null
@@ -0,0 +1,838 @@
+# Commands covered: expr
+#
+# This file contains the original set of tests for Tcl's expr command.
+# Since the expr command is now compiled, a new set of tests covering
+# the new implementation are in the files "parseExpr.test and
+# "compExpr.test". Sourcing this file into Tcl runs the tests and generates
+# output for errors. No output means no errors were found.
+#
+# Copyright (c) 1991-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: expr-old.test,v 1.8.2.1 2002/04/18 13:10:27 msofer Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+# First, test all of the integer operators individually.
+
+test expr-old-1.1 {integer operators} {expr -4} -4
+test expr-old-1.2 {integer operators} {expr -(1+4)} -5
+test expr-old-1.3 {integer operators} {expr ~3} -4
+test expr-old-1.4 {integer operators} {expr !2} 0
+test expr-old-1.5 {integer operators} {expr !0} 1
+test expr-old-1.6 {integer operators} {expr 4*6} 24
+test expr-old-1.7 {integer operators} {expr 36/12} 3
+test expr-old-1.8 {integer operators} {expr 27/4} 6
+test expr-old-1.9 {integer operators} {expr 27%4} 3
+test expr-old-1.10 {integer operators} {expr 2+2} 4
+test expr-old-1.11 {integer operators} {expr 2-6} -4
+test expr-old-1.12 {integer operators} {expr 1<<3} 8
+test expr-old-1.13 {integer operators} {expr 0xff>>2} 63
+test expr-old-1.14 {integer operators} {expr -1>>2} -1
+test expr-old-1.15 {integer operators} {expr 3>2} 1
+test expr-old-1.16 {integer operators} {expr 2>2} 0
+test expr-old-1.17 {integer operators} {expr 1>2} 0
+test expr-old-1.18 {integer operators} {expr 3<2} 0
+test expr-old-1.19 {integer operators} {expr 2<2} 0
+test expr-old-1.20 {integer operators} {expr 1<2} 1
+test expr-old-1.21 {integer operators} {expr 3>=2} 1
+test expr-old-1.22 {integer operators} {expr 2>=2} 1
+test expr-old-1.23 {integer operators} {expr 1>=2} 0
+test expr-old-1.24 {integer operators} {expr 3<=2} 0
+test expr-old-1.25 {integer operators} {expr 2<=2} 1
+test expr-old-1.26 {integer operators} {expr 1<=2} 1
+test expr-old-1.27 {integer operators} {expr 3==2} 0
+test expr-old-1.28 {integer operators} {expr 2==2} 1
+test expr-old-1.29 {integer operators} {expr 3!=2} 1
+test expr-old-1.30 {integer operators} {expr 2!=2} 0
+test expr-old-1.31 {integer operators} {expr 7&0x13} 3
+test expr-old-1.32 {integer operators} {expr 7^0x13} 20
+test expr-old-1.33 {integer operators} {expr 7|0x13} 23
+test expr-old-1.34 {integer operators} {expr 0&&1} 0
+test expr-old-1.35 {integer operators} {expr 0&&0} 0
+test expr-old-1.36 {integer operators} {expr 1&&3} 1
+test expr-old-1.37 {integer operators} {expr 0||1} 1
+test expr-old-1.38 {integer operators} {expr 3||0} 1
+test expr-old-1.39 {integer operators} {expr 0||0} 0
+test expr-old-1.40 {integer operators} {expr 3>2?44:66} 44
+test expr-old-1.41 {integer operators} {expr 2>3?44:66} 66
+test expr-old-1.42 {integer operators} {expr 36/5} 7
+test expr-old-1.43 {integer operators} {expr 36%5} 1
+test expr-old-1.44 {integer operators} {expr -36/5} -8
+test expr-old-1.45 {integer operators} {expr -36%5} 4
+test expr-old-1.46 {integer operators} {expr 36/-5} -8
+test expr-old-1.47 {integer operators} {expr 36%-5} -4
+test expr-old-1.48 {integer operators} {expr -36/-5} 7
+test expr-old-1.49 {integer operators} {expr -36%-5} -1
+test expr-old-1.50 {integer operators} {expr +36} 36
+test expr-old-1.51 {integer operators} {expr +--++36} 36
+test expr-old-1.52 {integer operators} {expr +36%+5} 1
+test expr-old-1.53 {integer operators} {
+    catch {unset x}
+    set x 1
+    list [expr {1 && $x}] [expr {$x && 1}] \
+         [expr {0 || $x}] [expr {$x || 0}]
+} {1 1 1 1}
+
+# Check the floating-point operators individually, along with
+# automatic conversion to integers where needed.
+
+test expr-old-2.1 {floating-point operators} {expr -4.2} -4.2
+test expr-old-2.2 {floating-point operators} jim {expr -(1.1+4.2)} -5.3
+test expr-old-2.3 {floating-point operators} {expr +5.7} 5.7
+test expr-old-2.4 {floating-point operators} {expr +--+-62.0} -62.0
+test expr-old-2.5 {floating-point operators} {expr !2.1} 0
+test expr-old-2.6 {floating-point operators} {expr !0.0} 1
+test expr-old-2.7 {floating-point operators} {expr 4.2*6.3} 26.46
+test expr-old-2.8 {floating-point operators} {expr 36.0/12.0} 3.0
+test expr-old-2.9 {floating-point operators} {expr 27/4.0} 6.75
+test expr-old-2.10 {floating-point operators} {expr 2.3+2.1} 4.4
+test expr-old-2.11 {floating-point operators} {expr 2.3-6.5} -4.2
+test expr-old-2.12 {floating-point operators} {expr 3.1>2.1} 1
+test expr-old-2.13 {floating-point operators} {expr {2.1 > 2.1}} 0
+test expr-old-2.14 {floating-point operators} {expr 1.23>2.34e+1} 0
+test expr-old-2.15 {floating-point operators} {expr 3.45<2.34} 0
+test expr-old-2.16 {floating-point operators} {expr 0.002e3<--200e-2} 0
+test expr-old-2.17 {floating-point operators} {expr 1.1<2.1} 1
+test expr-old-2.18 {floating-point operators} {expr 3.1>=2.2} 1
+test expr-old-2.19 {floating-point operators} {expr 2.345>=2.345} 1
+test expr-old-2.20 {floating-point operators} {expr 1.1>=2.2} 0
+test expr-old-2.21 {floating-point operators} {expr 3.0<=2.0} 0
+test expr-old-2.22 {floating-point operators} {expr 2.2<=2.2} 1
+test expr-old-2.23 {floating-point operators} {expr 2.2<=2.2001} 1
+test expr-old-2.24 {floating-point operators} {expr 3.2==2.2} 0
+test expr-old-2.25 {floating-point operators} {expr 2.2==2.2} 1
+test expr-old-2.26 {floating-point operators} {expr 3.2!=2.2} 1
+test expr-old-2.27 {floating-point operators} {expr 2.2!=2.2} 0
+test expr-old-2.28 {floating-point operators} {expr 0.0&&0.0} 0
+test expr-old-2.29 {floating-point operators} {expr 0.0&&1.3} 0
+test expr-old-2.30 {floating-point operators} {expr 1.3&&0.0} 0
+test expr-old-2.31 {floating-point operators} {expr 1.3&&3.3} 1
+test expr-old-2.32 {floating-point operators} {expr 0.0||0.0} 0
+test expr-old-2.33 {floating-point operators} {expr 0.0||1.3} 1
+test expr-old-2.34 {floating-point operators} {expr 1.3||0.0} 1
+test expr-old-2.35 {floating-point operators} {expr 3.3||0.0} 1
+test expr-old-2.36 {floating-point operators} {expr 3.3>2.3?44.3:66.3} 44.3
+test expr-old-2.37 {floating-point operators} {expr 2.3>3.3?44.3:66.3} 66.3
+test expr-old-2.38 {floating-point operators} {
+    list [catch {expr 028.1 + 09.2} msg] $msg
+} {0 37.3}
+
+# Operators that aren't legal on floating-point numbers
+
+test expr-old-3.1 {illegal floating-point operations} {
+    list [catch {expr ~4.0} msg]
+} {1}
+test expr-old-3.2 {illegal floating-point operations} {
+    list [catch {expr 27%4.0} msg]
+} {1}
+test expr-old-3.3 {illegal floating-point operations} {
+    list [catch {expr 27.0%4} msg]
+} {1}
+test expr-old-3.4 {illegal floating-point operations} {
+    list [catch {expr 1.0<<3} msg]
+} {1}
+test expr-old-3.5 {illegal floating-point operations} {
+    list [catch {expr 3<<1.0} msg]
+} {1}
+test expr-old-3.6 {illegal floating-point operations} {
+    list [catch {expr 24.0>>3} msg]
+} {1}
+test expr-old-3.7 {illegal floating-point operations} {
+    list [catch {expr 24>>3.0} msg]
+} {1}
+test expr-old-3.8 {illegal floating-point operations} {
+    list [catch {expr 24&3.0} msg]
+} {1}
+test expr-old-3.9 {illegal floating-point operations} {
+    list [catch {expr 24.0|3} msg]
+} {1}
+test expr-old-3.10 {illegal floating-point operations} {
+    list [catch {expr 24.0^3} msg]
+} {1}
+
+# Check the string operators individually.
+
+test expr-old-4.1 {string operators} {expr {"abc" > "def"}} 0
+test expr-old-4.2 {string operators} {expr {"def" > "def"}} 0
+test expr-old-4.3 {string operators} {expr {"g" > "def"}} 1
+test expr-old-4.4 {string operators} {expr {"abc" < "abd"}} 1
+test expr-old-4.5 {string operators} {expr {"abd" < "abd"}} 0
+test expr-old-4.6 {string operators} {expr {"abe" < "abd"}} 0
+test expr-old-4.7 {string operators} {expr {"abc" >= "def"}} 0
+test expr-old-4.8 {string operators} {expr {"def" >= "def"}} 1
+test expr-old-4.9 {string operators} {expr {"g" >= "def"}} 1
+test expr-old-4.10 {string operators} {expr {"abc" <= "abd"}} 1
+test expr-old-4.11 {string operators} {expr {"abd" <= "abd"}} 1
+test expr-old-4.12 {string operators} {expr {"abe" <= "abd"}} 0
+test expr-old-4.13 {string operators} {expr {"abc" == "abd"}} 0
+test expr-old-4.14 {string operators} {expr {"abd" == "abd"}} 1
+test expr-old-4.15 {string operators} {expr {"abc" != "abd"}} 1
+test expr-old-4.16 {string operators} {expr {"abd" != "abd"}} 0
+test expr-old-4.17 {string operators} {expr {"0y" < "0x12"}} 0
+test expr-old-4.18 {string operators} {expr {"." < " "}} 0
+
+# The following tests are non-portable because on some systems "+"
+# and "-" can be parsed as numbers.
+
+test expr-old-4.19 {string operators} {expr {"0" == "+"}} 0
+test expr-old-4.20 {string operators} {expr {"0" == "-"}} 0
+test expr-old-4.21 {string operators} {expr {1?"foo":"bar"}} foo
+test expr-old-4.22 {string operators} {expr {0?"foo":"bar"}} bar
+
+# Operators that aren't legal on string operands.
+
+test expr-old-5.1 {illegal string operations} {
+    list [catch {expr {-"a"}} msg]
+} {1}
+test expr-old-5.2 {illegal string operations} {
+    list [catch {expr {+"a"}} msg]
+} {1}
+test expr-old-5.3 {illegal string operations} {
+    list [catch {expr {~"a"}} msg]
+} {1}
+test expr-old-5.4 {illegal string operations} {
+    list [catch {expr {!"a"}} msg]
+} {1}
+test expr-old-5.5 {illegal string operations} {
+    list [catch {expr {"a"*"b"}} msg]
+} {1}
+test expr-old-5.6 {illegal string operations} {
+    list [catch {expr {"a"/"b"}} msg]
+} {1}
+test expr-old-5.7 {illegal string operations} {
+    list [catch {expr {"a"%"b"}} msg]
+} {1}
+test expr-old-5.8 {illegal string operations} {
+    list [catch {expr {"a"+"b"}} msg]
+} {1}
+test expr-old-5.9 {illegal string operations} {
+    list [catch {expr {"a"-"b"}} msg]
+} {1}
+test expr-old-5.10 {illegal string operations} {
+    list [catch {expr {"a"<<"b"}} msg]
+} {1}
+test expr-old-5.11 {illegal string operations} {
+    list [catch {expr {"a">>"b"}} msg]
+} {1}
+test expr-old-5.12 {illegal string operations} {
+    list [catch {expr {"a"&"b"}} msg]
+} {1}
+test expr-old-5.13 {illegal string operations} {
+    list [catch {expr {"a"^"b"}} msg]
+} {1}
+test expr-old-5.14 {illegal string operations} {
+    list [catch {expr {"a"|"b"}} msg]
+} {1}
+test expr-old-5.15 {illegal string operations} {
+    list [catch {expr {"a"&&"b"}} msg]
+} {1}
+test expr-old-5.16 {illegal string operations} {
+    list [catch {expr {"a"||"b"}} msg]
+} {1}
+test expr-old-5.17 {illegal string operations} {
+    list [catch {expr {"a"?4:2}} msg]
+} {1}
+
+# Check precedence pairwise.
+
+test expr-old-6.1 {precedence checks} {expr -~3} 4
+test expr-old-6.2 {precedence checks} {expr -!3} 0
+test expr-old-6.3 {precedence checks} {expr -~0} 1
+
+test expr-old-7.1 {precedence checks} {expr 2*4/6} 1
+test expr-old-7.2 {precedence checks} {expr 24/6*3} 12
+test expr-old-7.3 {precedence checks} {expr 24/6/2} 2
+
+test expr-old-8.1 {precedence checks} {expr -2+4} 2
+test expr-old-8.2 {precedence checks} {expr -2-4} -6
+test expr-old-8.3 {precedence checks} {expr +2-4} -2
+
+test expr-old-9.1 {precedence checks} {expr 2*3+4} 10
+test expr-old-9.2 {precedence checks} {expr 8/2+4} 8
+test expr-old-9.3 {precedence checks} {expr 8%3+4} 6
+test expr-old-9.4 {precedence checks} {expr 2*3-1} 5
+test expr-old-9.5 {precedence checks} {expr 8/2-1} 3
+test expr-old-9.6 {precedence checks} {expr 8%3-1} 1
+
+test expr-old-10.1 {precedence checks} {expr 6-3-2} 1
+
+test expr-old-11.1 {precedence checks} {expr 7+1>>2} 2
+test expr-old-11.2 {precedence checks} {expr 7+1<<2} 32
+test expr-old-11.3 {precedence checks} {expr 7>>3-2} 3
+test expr-old-11.4 {precedence checks} {expr 7<<3-2} 14
+
+test expr-old-12.1 {precedence checks} {expr 6>>1>4} 0
+test expr-old-12.2 {precedence checks} {expr 6>>1<2} 0
+test expr-old-12.3 {precedence checks} {expr 6>>1>=3} 1
+test expr-old-12.4 {precedence checks} {expr 6>>1<=2} 0
+test expr-old-12.5 {precedence checks} {expr 6<<1>5} 1
+test expr-old-12.6 {precedence checks} {expr 6<<1<5} 0
+test expr-old-12.7 {precedence checks} {expr 5<=6<<1} 1
+test expr-old-12.8 {precedence checks} {expr 5>=6<<1} 0
+
+test expr-old-13.1 {precedence checks} {expr 2<3<4} 1
+test expr-old-13.2 {precedence checks} {expr 0<4>2} 0
+test expr-old-13.3 {precedence checks} {expr 4>2<1} 0
+test expr-old-13.4 {precedence checks} {expr 4>3>2} 0
+test expr-old-13.5 {precedence checks} {expr 4>3>=2} 0
+test expr-old-13.6 {precedence checks} {expr 4>=3>2} 0
+test expr-old-13.7 {precedence checks} {expr 4>=3>=2} 0
+test expr-old-13.8 {precedence checks} {expr 0<=4>=2} 0
+test expr-old-13.9 {precedence checks} {expr 4>=2<=0} 0
+test expr-old-13.10 {precedence checks} {expr 2<=3<=4} 1
+
+test expr-old-14.1 {precedence checks} {expr 1==4>3} 1
+test expr-old-14.2 {precedence checks} {expr 0!=4>3} 1
+test expr-old-14.3 {precedence checks} {expr 1==3<4} 1
+test expr-old-14.4 {precedence checks} {expr 0!=3<4} 1
+test expr-old-14.5 {precedence checks} {expr 1==4>=3} 1
+test expr-old-14.6 {precedence checks} {expr 0!=4>=3} 1
+test expr-old-14.7 {precedence checks} {expr 1==3<=4} 1
+test expr-old-14.8 {precedence checks} {expr 0!=3<=4} 1
+
+test expr-old-15.1 {precedence checks} {expr 1==3==3} 0
+test expr-old-15.2 {precedence checks} {expr 3==3!=2} 1
+test expr-old-15.3 {precedence checks} {expr 2!=3==3} 0
+test expr-old-15.4 {precedence checks} {expr 2!=1!=1} 0
+
+test expr-old-16.1 {precedence checks} {expr 2&3==2} 0
+test expr-old-16.2 {precedence checks} {expr 1&3!=3} 0
+
+test expr-old-17.1 {precedence checks} {expr 7&3^0x10} 19
+test expr-old-17.2 {precedence checks} {expr 7^0x10&3} 7
+
+test expr-old-18.1 {precedence checks} {expr 7^0x10|3} 23
+test expr-old-18.2 {precedence checks} {expr 7|0x10^3} 23
+
+test expr-old-19.1 {precedence checks} {expr 7|3&&1} 1
+test expr-old-19.2 {precedence checks} {expr 1&&3|7} 1
+test expr-old-19.3 {precedence checks} {expr 0&&1||1} 1
+test expr-old-19.4 {precedence checks} {expr 1||1&&0} 1
+
+test expr-old-20.1 {precedence checks} {expr 1||0?3:4} 3
+test expr-old-20.2 {precedence checks} {expr 1?0:4||1} 0
+test expr-old-20.3 {precedence checks} {expr 1?2:0?3:4} 2
+test expr-old-20.4 {precedence checks} {expr 0?2:0?3:4} 4
+test expr-old-20.5 {precedence checks} {expr 1?2?3:4:0} 3
+test expr-old-20.6 {precedence checks} {expr 0?2?3:4:0} 0
+test expr-old-20.7 {precedence checks} {expr 0?1?1?2:3:0?4:5:1?0?6:7:0?8:9} 7
+
+
+# Parentheses.
+
+test expr-old-21.1 {parenthesization} {expr (2+4)*6} 36
+test expr-old-21.2 {parenthesization} {expr (1?0:4)||1} 1
+test expr-old-21.3 {parenthesization} {expr +(3-4)} -1
+
+# Embedded commands and variable names.
+
+set a 16 
+test expr-old-22.1 {embedded variables} {expr {2*$a}} 32 
+test expr-old-22.2 {embedded variables} {
+    set x -5
+    set y 10
+    expr {$x + $y}
+} {5} 
+test expr-old-22.3 {embedded variables} {
+    set x "  -5"
+    set y "  +10"
+    expr {$x + $y}
+} {5}
+test expr-old-22.4 {embedded commands and variables} {expr {[set a] - 14}} 2
+test expr-old-22.5 {embedded commands and variables} {
+    list [catch {expr {12 - [bad_command_name]}} msg] $msg
+} {1 {invalid command name "bad_command_name"}}
+
+# Double-quotes and things inside them.
+
+test expr-old-23.1 {double quotes} {expr {"abc"}} abc
+test expr-old-23.2 {double quotes} {
+    set a 189
+    expr {"$a.bc"}
+} 189.bc
+test expr-old-23.3 {double quotes} {
+    set b2 xyx
+    expr {"$b2$b2$b2.[set b2].[set b2]"}
+} xyxxyxxyx.xyx.xyx
+test expr-old-23.4 {double quotes} {expr {"11\}\}22"}} 11}}22
+test expr-old-23.5 {double quotes} {expr {"\*bc"}} {*bc}
+test expr-old-23.6 {double quotes} {
+    catch {unset bogus__}
+    list [catch {expr {"$bogus__"}} msg] $msg
+} {1 {can't read "bogus__": no such variable}}
+test expr-old-23.7 {double quotes} {
+    list [catch {expr {"a[error Testing]bc"}} msg] $msg
+} {1 Testing}
+test expr-old-23.8 {double quotes} {
+    list [catch {expr {"12398712938788234-1298379" != ""}} msg] $msg
+} {0 1}
+
+# Numbers in various bases.
+
+test expr-old-24.1 {numbers in different bases} {expr 0x20} 32
+test expr-old-24.2 {numbers in different bases} {expr 015} 15
+
+# Conversions between various data types.
+
+test expr-old-25.1 {type conversions} {expr 2+2.5} 4.5
+test expr-old-25.2 {type conversions} {expr 2.5+2} 4.5
+test expr-old-25.3 {type conversions} {expr 2-2.5} -0.5
+test expr-old-25.4 {type conversions} {expr 2/2.5} 0.8
+test expr-old-25.5 {type conversions} {expr 2>2.5} 0
+test expr-old-25.6 {type conversions} {expr 2.5>2} 1
+test expr-old-25.7 {type conversions} {expr 2<2.5} 1
+test expr-old-25.8 {type conversions} {expr 2>=2.5} 0
+test expr-old-25.9 {type conversions} {expr 2<=2.5} 1
+test expr-old-25.10 {type conversions} {expr 2==2.5} 0
+test expr-old-25.11 {type conversions} {expr 2!=2.5} 1
+test expr-old-25.12 {type conversions} {expr 2>"ab"} 0
+test expr-old-25.13 {type conversions} {expr {2>" "}} 1
+test expr-old-25.14 {type conversions} {expr {"24.1a" > 24.1}} 1
+test expr-old-25.15 {type conversions} {expr {24.1 > "24.1a"}} 0
+test expr-old-25.16 {type conversions} {expr 2+2.5} 4.5
+test expr-old-25.17 {type conversions} {expr 2+2.5} 4.5
+test expr-old-25.18 {type conversions} {expr 2.0e2} 200.0
+test expr-old-25.19 {type conversions} {expr 2.0e30} 2e+30
+test expr-old-25.20 {type conversions} {expr 10.0} 10.0
+
+# Various error conditions.
+
+test expr-old-26.1 {error conditions} {
+    list [catch {expr 2+"a"} msg]
+} {1}
+test expr-old-26.2 {error conditions} {
+    list [catch {expr 2+4*} msg]
+} {1}
+test expr-old-26.3 {error conditions} {
+    list [catch {expr 2+4*(} msg]
+} {1}
+catch {unset _non_existent_}
+test expr-old-26.4 {error conditions} {
+    list [catch {expr 2+$_non_existent_} msg]
+} {1}
+set a xx
+test expr-old-26.5 {error conditions} {
+    list [catch {expr {2+$a}} msg]
+} {1}
+test expr-old-26.6 {error conditions} {
+    list [catch {expr {2+[set a]}} msg]
+} {1}
+test expr-old-26.7 {error conditions} {
+    list [catch {expr {2+(4}} msg]
+} {1}
+test expr-old-26.8 {error conditions} {
+    list [catch {expr 2/0} msg]
+} {1}
+test expr-old-26.9 {error conditions} {
+    list [catch {expr 2%0} msg]
+} {1}
+test expr-old-26.10 {error conditions} {
+    expr 2.0/0.0
+} {Inf}
+test expr-old-26.11 {error conditions} {
+    list [catch {expr 2#} msg]
+} {1}
+test expr-old-26.12 {error conditions} {
+    list [catch {expr a.b} msg]
+} {1}
+test expr-old-26.13 {error conditions} {
+    list [catch {expr {"a"/"b"}} msg]
+} {1}
+test expr-old-26.14 {error conditions} {
+    list [catch {expr 2:3} msg]
+} {1}
+test expr-old-26.15 {error conditions} {
+    list [catch {expr a@b} msg]
+} {1}
+test expr-old-26.16 {error conditions} {
+    list [catch {expr a[b} msg]
+} {1}
+test expr-old-26.17 {error conditions} {
+    list [catch {expr a`b} msg]
+} {1}
+test expr-old-26.18 {error conditions} {
+    list [catch {expr \"a\"\{b} msg]
+} {1}
+test expr-old-26.19 {error conditions} {
+    list [catch {expr a} msg]
+} {1}
+test expr-old-26.20 {error conditions} {
+    list [catch expr msg]
+} {1}
+
+# Cancelled evaluation.
+
+test expr-old-27.1 {cancelled evaluation} {
+    set a 1
+    expr {0&&[set a 2]}
+    set a
+} 1
+test expr-old-27.2 {cancelled evaluation} {
+    set a 1
+    expr {1||[set a 2]}
+    set a
+} 1
+test expr-old-27.3 {cancelled evaluation} {
+    set a 1
+    expr {0?[set a 2]:1}
+    set a
+} 1
+test expr-old-27.4 {cancelled evaluation} {
+    set a 1
+    expr {1?2:[set a 2]}
+    set a
+} 1
+catch {unset x}
+test expr-old-27.5 {cancelled evaluation} {
+    list [catch {expr {[info exists x] && $x}} msg] $msg
+} {0 0}
+test expr-old-27.6 {cancelled evaluation} {
+    list [catch {expr {0 && [concat $x]}} msg] $msg
+} {0 0}
+test expr-old-27.7 {cancelled evaluation} {
+    set one 1
+    list [catch {expr {1 || 1/$one}} msg] $msg
+} {0 1}
+test expr-old-27.8 {cancelled evaluation} {
+    list [catch {expr {1 || -"string"}} msg] $msg
+} {0 1}
+test expr-old-27.9 {cancelled evaluation} {
+    list [catch {expr {1 || ("string" * ("x" && "y"))}} msg] $msg
+} {0 1}
+test expr-old-27.10 {cancelled evaluation} {
+    set x -1.3
+    list [catch {expr {($x > 0) ? round($x) : 0}} msg] $msg
+} {0 0}
+test expr-old-27.11 {cancelled evaluation} {
+    list [catch {expr {0 && foo}} msg]
+} {1}
+test expr-old-27.12 {cancelled evaluation} {
+    list [catch {expr {0 ? 1 : foo}} msg]
+} {1}
+
+# Operands enclosed in braces
+
+#test expr-old-29.1 {braces} {expr {{abc}}} abc
+#test expr-old-29.2 {braces} {expr {{00010}}} 8
+#test expr-old-29.3 {braces} {expr {{3.1200000}}} 3.12
+#test expr-old-29.4 {braces} {expr {{a{b}{1 {2 3}}c}}} "a{b}{1 {2 3}}c"
+#test expr-old-29.5 {braces} {
+#    list [catch {expr "\{abc"} msg] $msg
+#} {1 {missing close-brace}}
+
+# Very long values
+
+test expr-old-30.1 {long values} {
+    set a "0000 1111 2222 3333 4444"
+    set a "$a | $a | $a | $a | $a"
+    set a "$a || $a || $a || $a || $a"
+    expr {$a}
+} {0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 || 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444 | 0000 1111 2222 3333 4444}
+test expr-old-30.2 {long values} {
+    set a "000000000000000000000000000000"
+    set a "$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a${a}5"
+    expr $a
+} 5
+
+# Expressions spanning multiple arguments
+
+test expr-old-31.1 {multiple arguments to expr command} {
+    expr 4 + ( 6 *12) -3
+} 73
+test expr-old-31.2 {multiple arguments to expr command} {
+    list [catch {expr 2 + (3 + 4} msg]
+} {1}
+test expr-old-31.3 {multiple arguments to expr command} {
+    list [catch {expr 2 + 3 +} msg]
+} {1}
+test expr-old-31.4 {multiple arguments to expr command} {
+    list [catch {expr 2 + 3 )} msg]
+} {1}
+
+# Math functions
+
+if {0} {
+test expr-old-32.1 {math functions in expressions} {
+    format %.6g [expr acos(0.5)]
+} {1.0472}
+test expr-old-32.2 {math functions in expressions} {
+    format %.6g [expr asin(0.5)]
+} {0.523599}
+test expr-old-32.3 {math functions in expressions} {
+    format %.6g [expr atan(1.0)]
+} {0.785398}
+test expr-old-32.4 {math functions in expressions} {
+    format %.6g [expr atan2(2.0, 2.0)]
+} {0.785398}
+test expr-old-32.5 {math functions in expressions} {
+    format %.6g [expr ceil(1.999)]
+} {2}
+test expr-old-32.6 {math functions in expressions} {
+    format %.6g [expr cos(.1)]
+} {0.995004}
+test expr-old-32.7 {math functions in expressions} {
+    format %.6g [expr cosh(.1)]
+} {1.005}
+test expr-old-32.8 {math functions in expressions} {
+    format %.6g [expr exp(1.0)]
+} {2.71828}
+test expr-old-32.9 {math functions in expressions} {
+    format %.6g [expr floor(2.000)]
+} {2}
+test expr-old-32.10 {math functions in expressions} {
+    format %.6g [expr floor(2.001)]
+} {2}
+test expr-old-32.11 {math functions in expressions} {
+    format %.6g [expr fmod(7.3, 3.2)]
+} {0.9}
+test expr-old-32.12 {math functions in expressions} {
+    format %.6g [expr hypot(3.0, 4.0)]
+} {5}
+test expr-old-32.13 {math functions in expressions} {
+    format %.6g [expr log(2.8)]
+} {1.02962}
+test expr-old-32.14 {math functions in expressions} {
+    format %.6g [expr log10(2.8)]
+} {0.447158}
+test expr-old-32.15 {math functions in expressions} {
+    format %.6g [expr pow(2.1, 3.1)]
+} {9.97424}
+test expr-old-32.16 {math functions in expressions} {
+    format %.6g [expr sin(.1)]
+} {0.0998334}
+test expr-old-32.17 {math functions in expressions} {
+    format %.6g [expr sinh(.1)]
+} {0.100167}
+test expr-old-32.18 {math functions in expressions} {
+    format %.6g [expr sqrt(2.0)]
+} {1.41421}
+test expr-old-32.19 {math functions in expressions} {
+    format %.6g [expr tan(0.8)]
+} {1.02964}
+test expr-old-32.20 {math functions in expressions} {
+    format %.6g [expr tanh(0.8)]
+} {0.664037}
+}
+test expr-old-32.21 {math functions in expressions} {
+    format %.6g [expr abs(-1.8)]
+} {1.8}
+test expr-old-32.22 {math functions in expressions} {
+    expr abs(10.0)
+} {10.0}
+test expr-old-32.23 {math functions in expressions} {
+    format %.6g [expr abs(-4)]
+} {4}
+test expr-old-32.24 {math functions in expressions} {
+    format %.6g [expr abs(66)]
+} {66}
+
+# The following test is different for 32-bit versus 64-bit architectures.
+
+#test expr-old-32.25 {math functions in expressions} {
+#    list [catch {expr abs(0x8000000000000000)} msg] $msg
+#} {1 {integer value too large to represent}}
+
+test expr-old-32.26 {math functions in expressions} {
+    expr double(1)
+} {1.0}
+test expr-old-32.27 {math functions in expressions} {
+    expr double(1.1)
+} {1.1}
+test expr-old-32.28 {math functions in expressions} {
+    expr int(1)
+} {1}
+test expr-old-32.29 {math functions in expressions} {
+    expr int(1.4)
+} {1}
+test expr-old-32.30 {math functions in expressions} {
+    expr int(1.6)
+} {1}
+test expr-old-32.31 {math functions in expressions} {
+    expr int(-1.4)
+} {-1}
+test expr-old-32.32 {math functions in expressions} {
+    expr int(-1.6)
+} {-1}
+#test expr-old-32.33 {math functions in expressions} {
+#    list [catch {expr int(1e60)} msg] $msg
+#} {1 {integer value too large to represent}}
+#test expr-old-32.34 {math functions in expressions} {
+#    list [catch {expr int(-1e60)} msg] $msg
+#} {1 {integer value too large to represent}}
+test expr-old-32.35 {math functions in expressions} {
+    expr round(1.49)
+} {1}
+test expr-old-32.36 {math functions in expressions} {
+    expr round(1.51)
+} {2}
+test expr-old-32.37 {math functions in expressions} {
+    expr round(-1.49)
+} {-1}
+test expr-old-32.38 {math functions in expressions} {
+    expr round(-1.51)
+} {-2}
+#test expr-old-32.39 {math functions in expressions} {
+#    list [catch {expr round(1e60)} msg] $msg
+#} {1 {integer value too large to represent}}
+#test expr-old-32.40 {math functions in expressions} {
+#    list [catch {expr round(-1e60)} msg] $msg
+#} {1 {integer value too large to represent}}
+if {0} {
+test expr-old-32.41 {math functions in expressions} {
+    list [catch {expr pow(1.0 + 3.0 - 2, .8 * 5)} msg] $msg
+} {0 16.0}
+test expr-old-32.42 {math functions in expressions} {
+    list [catch {expr hypot(5*.8,3)} msg] $msg
+} {0 5.0}
+test expr-old-32.45 {math functions in expressions} {
+    expr (0 <= rand()) && (rand() < 1)
+} {1}
+test expr-old-32.46 {math functions in expressions} {
+    list [catch {expr rand(24)} msg] $msg
+} {1 {too many arguments for math function}}
+test expr-old-32.47 {math functions in expressions} {
+    list [catch {expr srand()} msg] $msg
+} {1 {too few arguments for math function}}
+test expr-old-32.48 {math functions in expressions} {
+    list [catch {expr srand(3.79)} msg] $msg
+} {1 {can't use floating-point value as argument to srand}}
+test expr-old-32.49 {math functions in expressions} {
+    list [catch {expr srand("")} msg] $msg
+} {1 {argument to math function didn't have numeric value}}
+test expr-old-32.50 {math functions in expressions} {
+    set result [expr round(srand(12345) * 1000)]
+    for {set i 0} {$i < 10} {incr i} {
+       lappend result [expr round(rand() * 1000)]
+    }
+    set result
+} {97 834 948 36 12 51 766 585 914 784 333}
+test expr-old-32.51 {math functions in expressions} {
+    list [catch {expr {srand([lindex "6ty" 0])}} msg] $msg
+} {1 {argument to math function didn't have numeric value}}
+
+test expr-old-33.1 {conversions and fancy args to math functions} {
+    expr hypot ( 3 , 4 )
+} 5.0
+test expr-old-33.2 {conversions and fancy args to math functions} {
+    expr hypot ( (2.0+1.0) , 4 )
+} 5.0
+test expr-old-33.3 {conversions and fancy args to math functions} {
+    expr hypot ( 3 , (3.0 + 1.0) )
+} 5.0
+test expr-old-33.4 {conversions and fancy args to math functions} {
+    format %.6g [expr cos(acos(0.1))]
+} 0.1
+
+test expr-old-34.1 {errors in math functions} {
+    list [catch {expr func_2(1.0)} msg] $msg
+} {1 {unknown math function "func_2"}}
+test expr-old-34.2 {errors in math functions} {
+    list [catch {expr func|(1.0)} msg] $msg
+} {1 {syntax error in expression "func|(1.0)"}}
+test expr-old-34.3 {errors in math functions} {
+    list [catch {expr {hypot("a b", 2.0)}} msg] $msg
+} {1 {argument to math function didn't have numeric value}}
+test expr-old-34.4 {errors in math functions} {
+    list [catch {expr hypot(1.0 2.0)} msg] $msg
+} {1 {syntax error in expression "hypot(1.0 2.0)"}}
+test expr-old-34.5 {errors in math functions} {
+    list [catch {expr hypot(1.0, 2.0} msg] $msg
+} {1 {syntax error in expression "hypot(1.0, 2.0"}}
+test expr-old-34.6 {errors in math functions} {
+    list [catch {expr hypot(1.0 ,} msg] $msg
+} {1 {syntax error in expression "hypot(1.0 ,"}}
+test expr-old-34.7 {errors in math functions} {
+    list [catch {expr hypot(1.0)} msg] $msg
+} {1 {too few arguments for math function}}
+test expr-old-34.8 {errors in math functions} {
+    list [catch {expr hypot(1.0, 2.0, 3.0)} msg] $msg
+} {1 {too many arguments for math function}}
+test expr-old-34.9 {errors in math functions} {
+    list [catch {expr acos(-2.0)} msg] $msg $errorCode
+} {1 {domain error: argument not in valid range} {ARITH DOMAIN {domain error: argument not in valid range}}}
+test expr-old-34.10 {errors in math functions} {
+    list [catch {expr pow(-3, 1000001)} msg] $msg $errorCode
+} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
+test expr-old-34.11 {errors in math functions} {
+    list [catch {expr pow(3, 1000001)} msg] $msg $errorCode
+} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
+test expr-old-34.12 {errors in math functions} {
+    list [catch {expr -14.0*exp(100000)} msg] $msg $errorCode
+} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
+test expr-old-34.13 {errors in math functions} {
+    list [catch {expr int(1.0e30)} msg] $msg $errorCode
+} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+test expr-old-34.14 {errors in math functions} {
+    list [catch {expr int(-1.0e30)} msg] $msg $errorCode
+} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+test expr-old-34.15 {errors in math functions} {
+    list [catch {expr round(1.0e30)} msg] $msg $errorCode
+} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+test expr-old-34.16 {errors in math functions} {
+    list [catch {expr round(-1.0e30)} msg] $msg $errorCode
+} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+
+test expr-old-36.1 {ExprLooksLikeInt procedure} {
+    list [catch {expr 0289} msg] $msg
+} {1 {"0289" is an invalid octal number}}
+test expr-old-36.2 {ExprLooksLikeInt procedure} {
+    set x 0289
+    list [catch {expr {$x+1}} msg] $msg
+} {1 {can't use invalid octal number as operand of "+"}}
+test expr-old-36.3 {ExprLooksLikeInt procedure} {
+    list [catch {expr 0289.1} msg] $msg
+} {0 289.1}
+test expr-old-36.4 {ExprLooksLikeInt procedure} {
+    set x 0289.1
+    list [catch {expr {$x+1}} msg] $msg
+} {0 290.1}
+test expr-old-36.5 {ExprLooksLikeInt procedure} {
+    set x {  +22}
+    list [catch {expr {$x+1}} msg] $msg
+} {0 23}
+test expr-old-36.6 {ExprLooksLikeInt procedure} {
+    set x {    -22}
+    list [catch {expr {$x+1}} msg] $msg
+} {0 -21}
+test expr-old-36.7 {ExprLooksLikeInt procedure} {
+    list [catch {expr nan} msg] $msg
+} {1 {domain error: argument not in valid range}}
+test expr-old-36.8 {ExprLooksLikeInt procedure} {
+    list [catch {expr 78e1} msg] $msg
+} {0 780.0}
+test expr-old-36.9 {ExprLooksLikeInt procedure} {
+    list [catch {expr 24E1} msg] $msg
+} {0 240.0}
+test expr-old-36.10 {ExprLooksLikeInt procedure} {
+    list [catch {expr 78e} msg] $msg
+} {1 {syntax error in expression "78e"}}
+}
+
+# test for [Bug #542588]
+# XXX: Can't rely on overflow checking
+#test expr-old-36.11 {ExprLooksLikeInt procedure} {
+#    # define a "too large integer"; this one works also for 64bit arith
+#    set x 665802003400000000000000
+#    list [catch {expr {$x+1}} msg] $msg
+#} {1 {can't use integer value too large to represent as operand of "+"}}
+
+# Special test for Pentium arithmetic bug of 1994:
+
+if {(4195835.0 - (4195835.0/3145727.0)*3145727.0) == 256.0} {
+    puts "Warning: this machine contains a defective Pentium processor"
+    puts "that performs arithmetic incorrectly.  I recommend that you"
+    puts "call Intel customer service immediately at 1-800-628-8686"
+    puts "to request a replacement processor."
+    puts [expr {(4195835.0 - (4195835.0/3145727.0)*3145727.0)}]
+}
+
+if {0.0 == 256.0} {
+    puts error
+}
+
+testreport
diff --git a/jim/tests/expr.test b/jim/tests/expr.test
new file mode 100755 (executable)
index 0000000..682af89
--- /dev/null
@@ -0,0 +1,138 @@
+source [file dirname [info script]]/testing.tcl
+
+test expr-1.1 "Compare strings lt" {
+       expr {"V000500" < "V000405"}
+} {0}
+
+test expr-1.2 "Compare strings with embedded nulls" {
+       set s1 [format abc%cdef 0]
+       set s2 [format abc%cghi 0]
+       expr {$s1 < $s2}
+} {1}
+
+test expr-1.3 "Hex values" {
+       set mask1 [expr 0x4050 & 0x0CCC]
+} {64}
+
+test expr-1.4 "Ternary operator - true" {
+       expr {1 ? 2 : 3}
+} {2}
+
+test expr-1.5 "Ternary operator - false" {
+       expr {0 ? 2 : 3}
+} {3}
+
+test expr-1.6 "Ternary operator - double check" {
+       expr {1.0 ? 2 : 3}
+} {2}
+
+test expr-1.7 "Ternary operator - string result" {
+       expr {1 ? "two" : 3}
+} {two}
+
+test expr-1.8 "Ternary operator - don't eval false path" {
+       set a 100
+       set b 200
+       set c [expr {20 ? [incr a] : [incr b]}]
+       list $a $b $c
+} {101 200 101}
+
+test expr-1.9 "Unary minus" {
+       set a 1
+       expr {-$a}
+} {-1}
+
+test expr-1.10 "Subtraction" {
+       set a 1
+       set b 10
+       expr {$b-$a}
+} {9}
+
+test expr-1.11 "Short circuit evaluation" {
+       set a 100
+       set c [expr {0 || [incr a]}]
+       list $a $c
+} {101 1}
+
+test expr-1.12 "Short circuit evaluation" {
+       set a 100
+       set c [expr {1 || [incr a]}]
+       list $a $c
+} {100 1}
+
+test expr-1.13 "Short circuit evaluation" {
+       set a 100
+       set c [expr {1 || [incr a] && [incr a]}]
+       list $a $c
+} {100 1}
+
+test expr-1.14 "Rotate left" jim {
+       expr {1 <<< 5}
+} {32}
+
+test expr-1.15 "Rotate left" jim {
+       expr {1 <<< 65}
+} {2}
+
+test expr-1.16 "Rotate right" jim {
+       expr {1 >>> 48}
+} {65536}
+
+test expr-1.17 "Rotate left" jim {
+       expr {1 >>> 63}
+} {2}
+
+# This crashes older jim
+test expr-2.1 "bogus unarymin" {
+       catch {expr {unarymin 1}}
+       return 1
+} {1}
+
+test expr-2.2 "Ternary operator - missing colon" {
+       list [catch {expr {1 ? 2 3}} msg]
+} {1}
+
+test expr-2.3 "Ternary operator - missing third term" {
+       list [catch {expr {1 ? 2}} msg]
+} {1}
+
+test expr-2.4 "Ternary operator - missing question" {
+       list [catch {expr {1 : 2}} msg]
+} {1}
+
+test expr-3.1 "in, ni operators" {
+       set l {a b c d}
+       set c C
+       list [expr {"a" in $l}] [expr {$c in $l}] [expr {"b" ni $l}] [expr {$c ni $l}]
+} {1 0 0 1}
+
+test expr-3.2 "if: in, ni operators" {
+       set l {a b c d}
+       set a a
+       set c C
+       set result {}
+       if {$a in $l} {
+               lappend result 1
+       }
+       if {$c in $l} {
+               lappend result 2
+       }
+       if {$a ni $l} {
+               lappend result 3
+       }
+       if {$c ni $l} {
+               lappend result 4
+       }
+       if {"d" in $l} {
+               lappend result 5
+       }
+} {1 4 5}
+
+# Don't want a to become 2.0
+test expr-4.1 "Shimmering" {
+       set a 2
+       expr {$a < 3.0}
+       set a
+} {2}
+
+testreport
diff --git a/jim/tests/exprsugar.test b/jim/tests/exprsugar.test
new file mode 100755 (executable)
index 0000000..9579203
--- /dev/null
@@ -0,0 +1,52 @@
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+
+# Test the expr-sugar syntax: $(...)
+
+test exprsugar-1.1 {Simple operations} {
+       set x $(2)
+} 2
+test exprsugar-1.2 {Simple operations} {
+       set x $(-3)
+} -3
+test exprsugar-1.3 {Simple operations} {
+       set x $(!0)
+} 1
+test exprsugar-1.4 {Simple operations} {
+       set a 3
+       set x $($a)
+} 3
+test exprsugar-1.5 {Simple operations} {
+       set x $($a + 4)
+} 7
+test exprsugar-1.6 {Simple operations} {
+       set x $(6 * 7 + 2)
+} 44
+test exprsugar-1.7 {Simple operations} {
+       set a bb
+       set x $($a in {aa bb cc})
+} 1
+test exprsugar-1.8 {Simple operations} {
+       set a 1
+       set x $($a ? "yes" : "no")
+} yes
+test exprsugar-1.9 {Simple operations} {
+       set a 1
+       set x $([incr a])
+       list $a $x
+} {2 2}
+# expr sugar inside an expression is an error
+test exprsugar-1.10 {Simple operations} {
+       catch {set x $(1 + $(5 * 7))}
+} 1
+test exprsugar-1.11 {Simple operations} {
+       unset a
+       set a(b) 3
+       set x $(2 + $a(b))
+} 5
+test exprsugar-1.12 {Simple operations} {
+       set x $((2 + 4))
+} 6
+
+testreport
diff --git a/jim/tests/filecopy.test b/jim/tests/filecopy.test
new file mode 100755 (executable)
index 0000000..084beec
--- /dev/null
@@ -0,0 +1,74 @@
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+needs cmd file
+needs cmd exec
+needs cmd parray tclcompat
+
+cd $testdir
+
+file mkdir tempdir
+
+test filecopy-1.1 "Simple case" {
+       file copy testio.in tempfile
+} {}
+
+test filecopy-1.2 "Target exists" {
+       list [catch {file copy testio.in tempfile} msg] $msg
+} {1 {error copying "testio.in" to "tempfile": file already exists}}
+
+test filecopy-1.3 "Source doesn't exist" {
+       list [catch {file copy missing tempfile} msg] $msg
+} {1 {missing: No such file or directory}}
+
+test filecopy-1.4 "Can't write to target" {
+       list [catch {file copy testio.in tempdir} msg] $msg
+} {1 {error copying "testio.in" to "tempdir": file already exists}}
+
+test filecopy-1.5 "Source doesn't exist and can't write to target" {
+       list [catch {file copy missing tempdir} msg] $msg
+} {1 {missing: No such file or directory}}
+
+test filecopy-1.6 "Wrong args" {
+       list [catch {file copy onearg} msg] $msg
+} {1 {wrong # args: should be "file copy ?-force? source dest"}}
+
+test filecopy-1.7 "Wrong args" {
+       list [catch {file copy too many args here} msg] $msg
+} {1 {wrong # args: should be "file copy ?-force? source dest"}}
+
+test filecopy-1.8 "Wrong args" {
+       list [catch {file copy -blah testio.in tempfile} msg] $msg
+} {1 {bad option "-blah": should be -force}}
+
+file delete tempfile
+
+test filecopy-2.1 "Simple case (-force)" {
+       file copy -force testio.in tempfile
+} {}
+
+test filecopy-2.2 "Target exists (-force)" {
+       file copy -force testio.in tempfile
+} {}
+
+test filecopy-2.3 "Source doesn't exist (-force)" {
+       list [catch {file copy -force missing tempfile} msg] $msg
+} {1 {missing: No such file or directory}}
+
+test filecopy-2.4 "Can't write to target (-force)" -body {
+       file copy -force testio.in tempdir
+} -returnCodes error -match glob -result {tempdir: *}
+
+test filecopy-2.5 "Source doesn't exist and can't write to target (-force)" {
+       list [catch {file copy -force missing tempdir} msg] $msg
+} {1 {missing: No such file or directory}}
+
+test filecopy-2.6 "Source and target identical (-force)" {
+       file copy -force tempfile tempfile
+       file size tempfile
+} 16
+
+file delete tempfile
+exec rm -rf tempdir
+
+testreport
diff --git a/jim/tests/filedir.test b/jim/tests/filedir.test
new file mode 100755 (executable)
index 0000000..4dd78ca
--- /dev/null
@@ -0,0 +1,68 @@
+source [file dirname [info script]]/testing.tcl
+
+needs cmd file
+needs cmd exec
+
+catch {
+       exec rm -rf tmp
+       exec mkdir tmp
+       exec touch tmp/file
+       exec mkdir tmp/dir
+}
+
+test mkdir-1.1 "Simple dir" {
+       file mkdir tmp/abc
+       file isdir tmp/abc
+} {1}
+
+test mkdir-1.2 "Create missing parents" {
+       file mkdir tmp/def/ghi/jkl
+       file isdir tmp/def/ghi/jkl
+} {1}
+
+test mkdir-1.3 "Existing dir" {
+       file mkdir tmp/dir
+       file isdir tmp/dir
+} {1}
+
+test mkdir-1.4 "Child of existing dir" {
+       file mkdir tmp/dir/child
+       file isdir tmp/dir/child
+} {1}
+
+test mkdir-1.5 "Create dir over existing file" {
+       list [catch {file mkdir tmp/file} msg] [file isdir tmp/file]
+} {1 0}
+
+test mkdir-1.6 "Create dir below existing file" {
+       list [catch {file mkdir tmp/file/dir} msg] [file isdir tmp/file/dir]
+} {1 0}
+
+test mkdir-1.8 "Multiple dirs" {
+       file mkdir tmp/1 tmp/2 tmp/3
+       list [file isdir tmp/1] [file isdir tmp/2] [file isdir tmp/3]
+} {1 1 1}
+
+test mkdir-1.7 "Stop on failure" {
+       catch {file mkdir tmp/4 tmp/file tmp/5}
+       list [file isdir tmp/4] [file isdir tmp/5]
+} {1 0}
+
+test rmdir-2.0 "Remove existing dir" {
+       file delete tmp/1
+       file isdir tmp/1
+} {0}
+
+test rmdir-2.1 "Remove missing dir" {
+       file delete tmp/1
+} {}
+
+test rmdir-2.2 "Remove non-empty dir" {
+       catch {file delete tmp/def}
+} {1}
+
+catch {
+       exec rm -rf tmp
+}
+
+testreport
diff --git a/jim/tests/filejoin.test b/jim/tests/filejoin.test
new file mode 100755 (executable)
index 0000000..7245938
--- /dev/null
@@ -0,0 +1,84 @@
+source [file dirname [info script]]/testing.tcl
+
+needs cmd file
+
+test join-1.1 "One name" {
+       file join abc
+} {abc}
+
+test join-1.2 "One name with trailing slash" {
+       file join abc/
+} {abc}
+
+test join-1.3 "One name with leading slash" {
+       file join /abc
+} {/abc}
+
+test join-1.4 "One name with leading and trailing slash" {
+       file join /abc/
+} {/abc}
+
+test join-1.5 "Two names" {
+       file join abc def
+} {abc/def}
+
+test join-1.6 "Two names with dir trailing slash" {
+       file join abc/ def
+} {abc/def}
+
+test join-1.7 "Two names with dir leading slash" {
+       file join /abc def
+} {/abc/def}
+
+test join-1.8 "Two names with dir leading and trailing slash" {
+       file join /abc/ def
+} {/abc/def}
+
+test join-1.9 "Two names with file trailing slash" {
+       file join abc def/
+} {abc/def}
+
+test join-1.10 "Two names with file leading slash" {
+       file join abc /def
+} {/def}
+
+test join-1.11 "Two names with file leading and trailing slash" {
+       file join abc /def/
+} {/def}
+
+test join-1.12 "Two names with double slashes" {
+       file join abc/ /def
+} {/def}
+
+test join-1.13 "Join to root" {
+       file join / abc
+} {/abc}
+
+test join-1.14 "Join to root" {
+       set dir [file join / .]
+       # Either / or /. is OK here
+       expr {$dir in {/ /.}}
+} 1
+
+test join-1.15 "Join to root" {
+       file join / /
+} {/}
+
+test join-1.16 "Join to root" {
+       file join /abc /
+} {/}
+
+test join-2.1 "Dir is empty string" {
+       file join "" def
+} {def}
+
+test join-2.2 "File is empty string" {
+       file join abc ""
+} {abc}
+
+test join-2.3 "Path too long" jim {
+       set components [string repeat {abcdefghi } 500]
+       list [catch [concat file join $components] msg] $msg
+} {1 {Path too long}}
+
+testreport
diff --git a/jim/tests/for.test b/jim/tests/for.test
new file mode 100755 (executable)
index 0000000..d12385a
--- /dev/null
@@ -0,0 +1,66 @@
+# Commands covered:  for, continue, break
+#
+# This file contains the original set of tests for Tcl's for command.
+# Since the for command is now compiled, a new set of tests covering
+# the new implementation is in the file "for.test". Sourcing this file
+# into Tcl runs the tests and generates output for errors.
+# No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: for-old.test,v 1.5 2000/04/10 17:18:59 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+# Check "for" and its use of continue and break.
+
+catch {unset a i}
+test for-old-1.1 {for tests} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3 4 5}
+test for-old-1.2 {for tests} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==4 continue
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3 5}
+test for-old-1.3 {for tests} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==4 break
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3}
+test for-old-1.4 {for tests} {catch {for 1 2 3} msg} 1
+test for-old-1.5 {for tests} {
+    catch {for 1 2 3} msg
+} {1}
+test for-old-1.6 {for tests} {catch {for 1 2 3 4 5} msg} 1
+test for-old-1.7 {for tests} {
+    catch {for 1 2 3 4 5} msg
+} {1}
+test for-old-1.8 {for tests} {
+    set a {xyz}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {}
+    set a
+} xyz
+test for-old-1.9 {for tests} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]; if $i==4 break} {
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3}
+
+testreport
diff --git a/jim/tests/format.test b/jim/tests/format.test
new file mode 100755 (executable)
index 0000000..d3d7f20
--- /dev/null
@@ -0,0 +1,517 @@
+# Commands covered:  format
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1994 The Regents of the University of California.
+# Copyright (c) 1994-1998 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: format.test,v 1.8 2000/04/10 17:18:59 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd format
+
+# The following code is needed because some versions of SCO Unix have
+# a round-off error in sprintf which would cause some of the tests to
+# fail.  Someday I hope this code shouldn't be necessary (code added
+# 9/9/91).
+
+set roundOffBug 0
+if {"[format %7.1e  68.514]" == "6.8e+01"} {
+    puts stdout "Note: this system has a sprintf round-off bug, some tests skipped\n"
+    set roundOffBug 1
+}
+
+test format-1.1 {integer formatting} {
+    format "%*d %d %d %d" 6 34 16923 -12 -1
+} {    34 16923 -12 -1}
+test format-1.2 {integer formatting} {
+    format "%4d %4d %4d %4d %d %#x %#X" 6 34 16923 -12 -1 14 12
+} {   6   34 16923  -12 -1 0xe 0XC}
+
+# %u output depends on word length, so this test is not portable.
+
+test format-1.3 {integer formatting} {
+    format "%4u %4u %4u %4u %d %#o" 6 34 16923 -12 -1 0
+} {   6   34 16923 18446744073709551604 -1 0}
+test format-1.4 {integer formatting} {
+    format "%-4d %-4i %-4d %-4ld" 6 34 16923 -12 -1
+} {6    34   16923 -12 }
+test format-1.5 {integer formatting} {
+    format "%04d %04d %04d %04i" 6 34 16923 -12 -1
+} {0006 0034 16923 -012}
+test format-1.6 {integer formatting} {
+    format "%00*d" 6 34
+} {000034}
+
+# Printing negative numbers in hex or octal format depends on word
+# length, so these tests are not portable.
+
+test format-1.7 {integer formatting} {
+    format "%4x %4x %4x %4x" 6 34 16923 -12 -1
+} {   6   22 421b fffffffffffffff4}
+test format-1.8 {integer formatting} {
+    format "%#x %#X %#X %#x" 6 34 16923 -12 -1
+} {0x6 0X22 0X421B 0xfffffffffffffff4}
+test format-1.9 {integer formatting} {
+    format "%#20x %#20x %#20x %#20x" 6 34 16923 -12 -1
+} {                 0x6                 0x22               0x421b   0xfffffffffffffff4}
+test format-1.10 {integer formatting} {
+    format "%-#20x %-#20x %-#20x %-#20x" 6 34 16923 -12 -1
+} {0x6                  0x22                 0x421b               0xfffffffffffffff4  }
+test format-1.11 {integer formatting} {
+    format "%-#20o %#-20o %#-20o %#-20o" 6 34 16923 -12 -1
+} {06                   042                  041033               01777777777777777777764}
+test format-1.12 {no sign extend large 32 bit values} {
+    format %x 0xa0000000
+} {a0000000}
+
+test format-2.1 {string formatting} {
+    format "%s %s %c %s" abcd {This is a very long test string.} 120 x
+} {abcd This is a very long test string. x x}
+test format-2.2 {string formatting} {
+    format "%20s %20s %20c %20s" abcd {This is a very long test string.} 120 x
+} {                abcd This is a very long test string.                    x                    x}
+test format-2.3 {string formatting} {
+    format "%.10s %.10s %c %.10s" abcd {This is a very long test string.} 120 x
+} {abcd This is a  x x}
+test format-2.4 {string formatting} {
+    format "%s %s %% %c %s" abcd {This is a very long test string.} 120 x
+} {abcd This is a very long test string. % x x}
+test format-2.5 {string formatting, embedded nulls} {
+    format "%10s" abc\0def
+} "   abc\0def"
+test format-2.6 {string formatting, international chars} utf8 {
+    format "%10s" abc\ufeffdef
+} "   abc\ufeffdef"
+test format-2.6 {string formatting, international chars} utf8 {
+    format "%.5s" abc\ufeffdef
+} "abc\ufeffd"
+test format-2.7 {string formatting, international chars} {
+    format "foo\ufeffbar%s" baz
+} "foo\ufeffbarbaz"
+test format-2.8 {string formatting, width} {
+    format "a%5sa" f
+} "a    fa"
+test format-2.8 {string formatting, width} {
+    format "a%-5sa" f
+} "af    a"
+test format-2.8 {string formatting, width} {
+    format "a%2sa" foo
+} "afooa"
+test format-2.8 {string formatting, width} {
+    format "a%0sa" foo
+} "afooa"
+test format-2.8 {string formatting, precision} {
+    format "a%.2sa" foobarbaz
+} "afoa"
+test format-2.8 {string formatting, precision} {
+    format "a%.sa" foobarbaz
+} "aa"
+test format-2.8 {string formatting, precision} {
+    list [catch {format "a%.-2sa" foobarbaz} msg] $msg
+} {1 {bad field specifier "-"}}
+test format-2.8 {string formatting, width and precision} {
+    format "a%5.2sa" foobarbaz
+} "a   foa"
+test format-2.8 {string formatting, width and precision} {
+    format "a%5.7sa" foobarbaz
+} "afoobarba"
+test format-3.1 {Tcl_FormatObjCmd: character formatting} utf8 {
+    format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 65 65 65 65 65 65 3 65 -4 65
+} "|A|A|A|A|A     |     A|  A|A   |"
+test format-3.2 {Tcl_FormatObjCmd: international character formatting} utf8 {
+    format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 0xa2 0x4e4e 0x25a 0xc3 0xff08 0 3 0x6575 -4 0x4e4f
+} "|\ua2|\u4e4e|\u25a|\uc3|\uff08     |     \0|  \u6575|\u4e4f   |"
+test format-4.1 {e and f formats} -body {
+    format "%e %e %e %e" 34.2e12 68.514 -.125 -16000. .000053
+} -match regexp -result {3.420000e\+0?13 6.851400e\+0?01 -1.250000e-0?01 -1.600000e\+0?04}
+test format-4.2 {e and f formats} -body {
+    format "%20e %20e %20e %20e" 34.2e12 68.514 -.125 -16000. .000053
+} -match regexp -result {(        3.420000e\+13         6.851400e\+01        -1.250000e-01        -1.600000e\+04|       3.420000e\+013        6.851400e\+001       -1.250000e-001       -1.600000e\+004)}
+
+test format-4.3 {e and f formats} -body {
+    format "%.1e %.1e %.1e %.1e" 34.2e12 68.514 -.126 -16000. .000053
+} -match regexp -result {3.4e\+0?13 6.9e\+0?01 -1.3e-0?01 -1.6e\+0?04}
+test format-4.4 {e and f formats} -body {
+    format "%020e %020e %020e %020e" 34.2e12 68.514 -.126 -16000. .000053
+} -match regexp -result {(000000003.420000e\+13 000000006.851400e\+01 -00000001.260000e-01 -00000001.600000e\+04|00000003.420000e\+013 00000006.851400e\+001 -0000001.260000e-001 -0000001.600000e\+004)}
+
+test format-4.5 {e and f formats} -body {
+    format "%7.1e %7.1e %7.1e %7.1e" 34.2e12 68.514 -.126 -16000. .000053
+} -match regexp -result {3.4e\+0?13 6.9e\+0?01 -1.3e-0?01 -1.6e\+0?04}
+test format-4.6 {e and f formats} {
+    format "%f %f %f %f" 34.2e12 68.514 -.125 -16000. .000053
+} {34200000000000.000000 68.514000 -0.125000 -16000.000000}
+test format-4.7 {e and f formats} {
+    format "%.4f %.4f %.4f %.4f %.4f" 34.2e12 68.514 -.125 -16000. .000053
+} {34200000000000.0000 68.5140 -0.1250 -16000.0000 0.0001}
+test format-4.8 {e and f formats} -body {
+    format "%.4e %.5e %.6e" -9.99996 -9.99996 9.99996
+} -match regexp -result {\-1.0000e\+0?01 -9.99996e\+0?00 9.999960e\+0?00}
+test format-4.9 {e and f formats} {
+    format "%.4f %.5f %.6f" -9.99996 -9.99996 9.99996
+} {-10.0000 -9.99996 9.999960}
+test format-4.10 {e and f formats} {
+    format "%20f %-20f %020f" -9.99996 -9.99996 9.99996
+} {           -9.999960 -9.999960            0000000000009.999960}
+test format-4.11 {e and f formats} {
+    format "%-020f %020f" -9.99996 -9.99996 9.99996
+} {-9.999960            -000000000009.999960}
+test format-4.12 {e and f formats} -body {
+    format "%.0e %#.0e" -9.99996 -9.99996 9.99996
+} -match regexp -result {\-1e\+0?01 -1.e\+0?01}
+test format-4.13 {e and f formats} {
+    format "%.0f %#.0f" -9.99996 -9.99996 9.99996
+} {-10 -10.}
+test format-4.14 {e and f formats} {
+    format "%.4f %.5f %.6f" -9.99996 -9.99996 9.99996
+} {-10.0000 -9.99996 9.999960}
+test format-4.15 {e and f formats} {
+    format "%3.0f %3.0f %3.0f %3.0f" 1.0 1.1 1.01 1.001
+} {  1   1   1   1}
+test format-4.16 {e and f formats} {
+    format "%3.1f %3.1f %3.1f %3.1f" 0.0 0.1 0.01 0.001
+} {0.0 0.1 0.0 0.0}
+
+test format-5.1 {g-format} -body {
+    format "%.3g" 12341.0
+} -match regexp -result {1.23e\+0?04}
+test format-5.2 {g-format} -body {
+    format "%.3G" 1234.12345
+} -match regexp -result {1.23E\+0?03}
+test format-5.3 {g-format} {
+    format "%.3g" 123.412345
+} {123}
+test format-5.4 {g-format} {
+    format "%.3g" 12.3412345
+} {12.3}
+test format-5.5 {g-format} {
+    format "%.3g" 1.23412345
+} {1.23}
+test format-5.6 {g-format} {
+    format "%.3g" 1.23412345
+} {1.23}
+test format-5.7 {g-format} {
+    format "%.3g" .123412345
+} {0.123}
+test format-5.8 {g-format} {
+    format "%.3g" .012341
+} {0.0123}
+test format-5.9 {g-format} {
+    format "%.3g" .0012341
+} {0.00123}
+test format-5.10 {g-format} {
+    format "%.3g" .00012341
+} {0.000123}
+test format-5.11 {g-format} -body {
+    format "%.3g" .00001234
+} -match regexp -result {1.23e-0?05}
+test format-5.12 {g-format} -body {
+    format "%.4g" 9999.6
+} -match regexp -result {1e\+0?04}
+test format-5.13 {g-format} {
+    format "%.4g" 999.96
+} {1000}
+test format-5.14 {g-format} {
+    format "%.3g" 1.0
+} {1}
+test format-5.15 {g-format} {
+    format "%.3g" .1
+} {0.1}
+test format-5.16 {g-format} {
+    format "%.3g" .01
+} {0.01}
+test format-5.17 {g-format} {
+    format "%.3g" .001
+} {0.001}
+test format-5.18 {g-format} -body {
+    format "%.3g" .00001
+} -match regexp -result {1e-0?05}
+test format-5.19 {g-format} -body {
+    format "%#.3g" 1234.0
+} -match regexp -result {1.23e\+0?03}
+test format-5.20 {g-format} -body {
+    format "%#.3G" 9999.5
+} -match regexp -result {1.00E\+0?04}
+
+test format-6.1 {floating-point zeroes} -body {
+    format "%e %f %g" 0.0 0.0 0.0 0.0
+} -match regexp -result {0.000000e\+0?00 0.000000 0}
+test format-6.2 {floating-point zeroes} -body {
+    format "%.4e %.4f %.4g" 0.0 0.0 0.0 0.0
+} -match regexp -result {0.0000e\+0?00 0.0000 0}
+test format-6.3 {floating-point zeroes} -body {
+    format "%#.4e %#.4f %#.4g" 0.0 0.0 0.0 0.0
+} -match regexp -result {0.0000e\+0?00 0.0000 0.000}
+test format-6.4 {floating-point zeroes} -body {
+    format "%.0e %.0f %.0g" 0.0 0.0 0.0 0.0
+} -match regexp -result {0e\+0?00 0 0}
+test format-6.5 {floating-point zeroes} -body {
+    format "%#.0e %#.0f %#.0g" 0.0 0.0 0.0 0.0
+} -match regexp -result {0.e\+0?00 0. 0.}
+test format-6.6 {floating-point zeroes} {
+    format "%3.0f %3.0f %3.0f %3.0f" 0.0 0.0 0.0 0.0
+} {  0   0   0   0}
+test format-6.7 {floating-point zeroes} {
+    format "%3.0f %3.0f %3.0f %3.0f" 1.0 1.1 1.01 1.001
+} {  1   1   1   1}
+test format-6.8 {floating-point zeroes} {
+    format "%3.1f %3.1f %3.1f %3.1f" 0.0 0.1 0.01 0.001
+} {0.0 0.1 0.0 0.0}
+
+test format-7.1 {various syntax features} {
+    format "%*.*f" 12 3 12.345678901
+} {      12.346}
+test format-7.2 {various syntax features} {
+    format "%0*.*f" 12 3 12.345678901
+} {00000012.346}
+test format-7.3 {various syntax features} {
+    format "\*\t\\n"
+} {*   \n}
+
+test format-8.1 {error conditions} {
+    catch format
+} 1
+test format-8.2 {error conditions} jim {
+    catch format msg
+    set msg
+} {wrong # args: should be "format formatString ?arg arg ...?"}
+test format-8.3 {error conditions} {
+    catch {format %*d}
+} 1
+test format-8.4 {error conditions} {
+    catch {format %*d} msg
+    set msg
+} {not enough arguments for all format specifiers}
+test format-8.5 {error conditions} {
+    catch {format %*.*f 12}
+} 1
+test format-8.6 {error conditions} {
+    catch {format %*.*f 12} msg
+    set msg
+} {not enough arguments for all format specifiers}
+test format-8.7 {error conditions} {
+    catch {format %*.*f 12 3}
+} 1
+test format-8.8 {error conditions} {
+    catch {format %*.*f 12 3} msg
+    set msg
+} {not enough arguments for all format specifiers}
+test format-8.9 {error conditions} {
+    list [catch {format %*d x 3} msg] $msg
+} {1 {expected integer but got "x"}}
+test format-8.10 {error conditions} {
+    list [catch {format %*.*f 2 xyz 3} msg] $msg
+} {1 {expected integer but got "xyz"}}
+test format-8.11 {error conditions} {
+    catch {format %d 2a}
+} 1
+test format-8.12 {error conditions} {
+    catch {format %d 2a} msg
+    set msg
+} {expected integer but got "2a"}
+test format-8.13 {error conditions} {
+    catch {format %c 2x}
+} 1
+test format-8.14 {error conditions} {
+    catch {format %c 2x} msg
+    set msg
+} {expected integer but got "2x"}
+test format-8.15 {error conditions} {
+    catch {format %f 2.1z}
+} 1
+test format-8.16 {error conditions} jim {
+    catch {format %f 2.1z} msg
+    set msg
+} {expected number but got "2.1z"}
+test format-8.17 {error conditions} {
+    catch {format ab%}
+} 1
+test format-8.18 {error conditions} {
+    catch {format ab% 12} msg
+    set msg
+} {format string ended in middle of field specifier}
+test format-8.19 {error conditions} {
+    catch {format %q x}
+} 1
+test format-8.20 {error conditions} {
+    catch {format %q x} msg
+    set msg
+} {bad field specifier "q"}
+test format-8.21 {error conditions} {
+    catch {format %d}
+} 1
+test format-8.22 {error conditions} {
+    catch {format %d} msg
+    set msg
+} {not enough arguments for all format specifiers}
+test format-8.23 {error conditions} {
+    catch {format "%d %d" 24 xyz} msg
+    set msg
+} {expected integer but got "xyz"}
+
+test format-9.1 {long result} {
+    set a {1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
+    format {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG %s %s} $a $a
+} {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
+
+test format-10.1 {"h" format specifier} {
+    format %hd 0xffff
+} -1
+test format-10.2 {"h" format specifier} {
+    format %hx 0x10fff
+} fff
+test format-10.3 {"h" format specifier} {
+    format %hd 0x10000
+} 0
+
+test format-11.1 {XPG3 %$n specifiers} {
+    format {%2$d %1$d} 4 5
+} {5 4}
+test format-11.2 {XPG3 %$n specifiers} {
+    format {%2$d %1$d %1$d %3$d} 4 5 6
+} {5 4 4 6}
+test format-11.3 {XPG3 %$n specifiers} {
+    list [catch {format {%2$d %3$d} 4 5} msg] $msg
+} {1 {"%n$" argument index out of range}}
+test format-11.4 {XPG3 %$n specifiers} {
+    list [catch {format {%2$d %0$d} 4 5 6} msg] $msg
+} {1 {"%n$" argument index out of range}}
+test format-11.5 {XPG3 %$n specifiers} {
+    list [catch {format {%d %1$d} 4 5 6} msg] $msg
+} {1 {cannot mix "%" and "%n$" conversion specifiers}}
+test format-11.6 {XPG3 %$n specifiers} {
+    list [catch {format {%2$d %d} 4 5 6} msg] $msg
+} {1 {cannot mix "%" and "%n$" conversion specifiers}}
+test format-11.7 {XPG3 %$n specifiers} {
+    list [catch {format {%2$d %3d} 4 5 6} msg] $msg
+} {1 {cannot mix "%" and "%n$" conversion specifiers}}
+test format-11.8 {XPG3 %$n specifiers} {
+    format {%2$*d %3$d} 1 10 4
+} {         4 4}
+test format-11.9 {XPG3 %$n specifiers} {
+    format {%2$.*s %4$d} 1 5 abcdefghijklmnop 44
+} {abcde 44}
+test format-11.10 {XPG3 %$n specifiers} {
+    list [catch {format {%2$*d} 4} msg] $msg
+} {1 {"%n$" argument index out of range}}
+test format-11.11 {XPG3 %$n specifiers} {
+    list [catch {format {%2$*d} 4 5} msg] $msg
+} {1 {"%n$" argument index out of range}}
+test format-11.12 {XPG3 %$n specifiers} {
+    list [catch {format {%2$*d} 4 5 6} msg] $msg
+} {0 {    6}}
+
+test format-12.1 {negative width specifiers} {
+    format "%*d" -47 25
+} {25                                             }
+test format-13.1 {tcl_precision fuzzy comparison} {
+    catch {unset a}
+    catch {unset b}
+    catch {unset c}
+    catch {unset d}
+    set a 0.0000000000001
+    set b 0.00000000000001
+    set c 0.00000000000000001
+    set d [expr $a + $b + $c]
+    format {%0.10f %0.12f %0.15f %0.17f} $d $d $d $d
+} {0.0000000000 0.000000000000 0.000000000000110 0.00000000000011001}
+test format-13.2 {tcl_precision fuzzy comparison} {
+    catch {unset a}
+    catch {unset b}
+    catch {unset c}
+    catch {unset d}
+    set a 0.000000000001
+    set b 0.000000000000005
+    set c 0.0000000000000008
+    set d [expr $a + $b + $c]
+    format {%0.10f %0.12f %0.15f %0.17f} $d $d $d $d
+} {0.0000000000 0.000000000001 0.000000000001006 0.00000000000100580}
+test format-13.3 {tcl_precision fuzzy comparison} {
+    catch {unset a}
+    catch {unset b}
+    catch {unset c}
+    set a 0.00000000000099
+    set b 0.000000000000011
+    set c [expr $a + $b]
+    format {%0.10f %0.12f %0.15f %0.17f} $c $c $c $c
+} {0.0000000000 0.000000000001 0.000000000001001 0.00000000000100100}
+test format-13.4 {tcl_precision fuzzy comparison} {
+    catch {unset a}
+    catch {unset b}
+    catch {unset c}
+    set a 0.444444444444
+    set b 0.33333333333333
+    set c [expr $a + $b]
+    format {%0.10f %0.12f %0.15f %0.16f} $c $c $c $c
+} {0.7777777778 0.777777777777 0.777777777777330 0.7777777777773300}
+test format-13.5 {tcl_precision fuzzy comparison} {
+    catch {unset a}
+    catch {unset b}
+    catch {unset c}
+    set a 0.444444444444
+    set b 0.99999999999999
+    set c [expr $a + $b]
+    format {%0.10f %0.12f %0.15f} $c $c $c
+} {1.4444444444 1.444444444444 1.444444444443990}
+test format-14.1 {testing MAX_FLOAT_SIZE for 0 and 1} {
+    format {%s} ""
+} {}
+test format-14.2 {testing MAX_FLOAT_SIZE for 0 and 1} {
+    format {%s} "a"
+} {a}
+
+test format-15.1 {testing %0..s 0 padding for chars/strings} {
+    format %05s a
+} {0000a}
+test format-15.2 {testing %0..s 0 padding for chars/strings} {
+    format "% 5s" a
+} {    a}
+test format-15.3 {testing %0..s 0 padding for chars/strings} {
+    format %5s a
+} {    a}
+test format-15.4 {testing %0..s 0 padding for chars/strings} {
+    format %05c 61
+} {0000=}
+
+set a "0123456789"
+set b ""
+for {set i 0} {$i < 290} {incr i} {
+    append b $a
+}
+for {set i 290} {$i < 400} {incr i} {
+    test format-15.[expr $i -290] {testing MAX_FLOAT_SIZE} {
+        format {%s} $b    
+    } $b
+    append b "x"
+}
+
+test format-16.1 {format %b} {
+    format %b 0
+} {0}
+
+test format-16.2 {format %b} {
+    format %b 1
+} {1}
+
+test format-16.3 {format %b} {
+    format %b 0xf
+} {1111}
+
+test format-16.4 {format %b} {
+    format %b 1234567
+} {100101101011010000111}
+
+# cleanup
+catch {unset a}
+catch {unset b}
+catch {unset c}
+catch {unset d}
+
+testreport
diff --git a/jim/tests/glob.test b/jim/tests/glob.test
new file mode 100755 (executable)
index 0000000..9bbdcd8
--- /dev/null
@@ -0,0 +1,131 @@
+# Test the glob command
+
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+needs cmd glob
+
+# Fake the bare minimum that glob.tcl needs:
+# [readdir], [file isdir] and [file exists]
+local proc file {cmd args} {
+       if {$cmd in {isdir exists}} {
+               lassign [fslookup [lindex $args 0]] type contents
+               if {$cmd eq "isdir" && $type eq "dir"} {
+                       return 1
+               } elseif {$type ne "none"} {
+                       return 1
+               }
+               return 0
+       }
+       tailcall upcall file $cmd {*}$args
+}
+
+local proc readdir {{-nocomplain {}} dir} {
+       lassign [fslookup $dir] type contents
+       if {$type ne "dir"} {
+               if {${-nocomplain} eq ""} {
+                       return {}
+               }
+               return -code error "No such file or directory"
+       }
+       dict keys $contents
+}
+
+local proc fslookup {path} {
+       set type dir
+       set dict $::FAKEFS
+       foreach p [split $path /] {
+               if {$p in {. {}}} {
+                       continue
+               }
+               if {![dict exists $dict $p] || $type ne "dir"} {
+                       return none
+               }
+               lassign [dict get $dict $p] type dict
+       }
+       list $type $dict
+}
+
+# Creates the representation of a filesystem in a dictionary - for testing
+local proc makefakefs {fs} {
+       set fakefs {}
+       foreach {type name contents} $fs {
+               switch -glob -- $type {
+                       f* {
+                               set fakefs($name) [list file $contents]
+                       }
+                       d* {
+                               set fakefs($name) [list dir [makefakefs $contents]]
+                       }
+                       default {
+                               error "Unknown fs type: $type"
+                       }
+               }
+       }
+       return $fakefs
+}
+
+# Create a fake filesystem for testing the glob command
+set ::FAKEFS [makefakefs {
+       file abc {This is the contents of abc}
+       dir def {
+               file ghi {This file is inside def}
+               dir jkl
+       }
+       dir tmp {
+               file "open{brace" {}
+               file "close}brace" {}
+               file "open\[bracket" {}
+               file "close\]bracket" {}
+       }
+}]
+
+test glob-1.1 {Simple} {
+       lsort [glob *]
+} {abc def tmp}
+
+test glob-1.2 {Simple} {
+       lsort [glob a*]
+} {abc}
+
+test glob-1.3 {Simple} -returnCodes error -body {
+       lsort [glob x*]
+} -result {no files matched glob patterns}
+
+test glob-1.4 {Simple} -returnCodes error -body {
+       lsort [glob]
+} -result {wrong # args: should be "glob ?options? pattern ?pattern ...?"}
+
+test glob-1.5 {Simple} -returnCodes ok -body {
+       lsort [glob -nocomplain x*]
+} -result {}
+
+test glob-2.1 {Braces} -returnCodes ok -body {
+       lsort [glob "{a,d}*"]
+} -result {abc def}
+
+test glob-2.2 {Files containing braces and brackets} -returnCodes ok -body {
+       lsort [glob tmp/*]
+} -result {tmp/close\]bracket tmp/close\}brace {tmp/open[bracket} tmp/open\{brace}
+
+test glob-2.3 {Glob match files open bracket} -returnCodes ok -body {
+       lsort [glob {tmp/*\[*}]
+} -result [list tmp/open\[bracket]
+
+test glob-2.4 {Glob match files close bracket} -returnCodes ok -body {
+       lsort [glob {tmp/*\]*}]
+} -result [list tmp/close\]bracket]
+
+test glob-2.5 {Glob match files containing braced brackets} -returnCodes ok -body {
+       lsort [glob {tmp/*{\[,]}*}]
+} -result [list tmp/close\]bracket tmp/open\[bracket]
+
+test glob-3.1 {Directory option} -returnCodes ok -body {
+       lsort [glob -dir tmp *]
+} -result [list close\]bracket close\}brace open\[bracket open\{brace]
+
+test glob-3.2 {Directory option} -returnCodes ok -body {
+       lsort [glob -dir tmp *close*]
+} -result [list close\]bracket close\}brace]
+
+testreport
diff --git a/jim/tests/infoframe.test b/jim/tests/infoframe.test
new file mode 100755 (executable)
index 0000000..f1619f5
--- /dev/null
@@ -0,0 +1,37 @@
+source [file dirname [info script]]/testing.tcl
+needs constraint jim
+proc a {n} {
+       if {$n eq "trace"} {
+               stacktrace
+       } else {
+               info frame $n
+       }
+}
+
+proc b {n} {
+       a $n
+}
+
+proc c {n} {
+       b $n
+}
+
+# --- Don't change line numbers above
+
+test info-frame-1.1 "Current proc" {
+       c 0
+} {a infoframe.test 12}
+
+test info-frame-1.2 "Caller" {
+       c -1
+} {b infoframe.test 16}
+
+test info-frame-1.3 "Caller of Caller" {
+       c -2
+} {c infoframe.test 30}
+
+test stacktrace-1.1 "Full stack trace" {
+       c trace
+} {a infoframe.test 12 b infoframe.test 16 c infoframe.test 34}
+
+testreport
diff --git a/jim/tests/jim.test b/jim/tests/jim.test
new file mode 100755 (executable)
index 0000000..c83a047
--- /dev/null
@@ -0,0 +1,3505 @@
+# $Id: test.tcl,v 1.31 2008/11/06 13:31:22 oharboe Exp $
+#
+# These are Tcl tests imported into Jim. Tests that will probably not be passed
+# in the long term are usually removed (for example all the tests about
+# unicode things, about errors in list parsing that are always valid in Jim
+# and so on).
+#
+# Sometimes tests are modified to reflect different error messages.
+
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+catch {package require regexp}
+testConstraint regexp [expr {[info commands regexp] ne {}}]
+testConstraint lambda [expr {[info commands ref] ne {}}]
+
+################################################################################
+# SET
+################################################################################
+
+test set-1.2 {TclCompileSetCmd: simple variable name} {
+    set i 10
+    list [set i] $i
+} {10 10}
+
+test set-1.4 {TclCompileSetCmd: simple variable name in quotes} {
+    set i 17
+    list [set "i"] $i
+} {17 17}
+
+test set-1.7 {TclCompileSetCmd: non-simple (computed) variable name} {
+    set x "i"
+    set i 77
+    list [set $x] $i
+} {77 77}
+
+test set-1.8 {TclCompileSetCmd: non-simple (computed) variable name} {
+    set x "i"
+    set i 77
+    list [set [set x] 2] $i
+} {2 2}
+
+test set-1.9 {TclCompileSetCmd: 3rd arg => assignment} {
+    set i "abcdef"
+    list [set i] $i
+} {abcdef abcdef}
+
+test set-1.10 {TclCompileSetCmd: only two args => just getting value} {
+    set i {one two}
+    set i
+} {one two}
+
+test set-1.11 {TclCompileSetCmd: simple global name} {
+    proc p {} {
+        global i
+        set i 54
+        set i
+    }
+    p
+} {54}
+
+test set-1.12 {TclCompileSetCmd: simple local name} {
+    proc p {bar} {
+        set foo $bar
+        set foo
+    }
+    p 999
+} {999}
+
+test set-1.14 {TclCompileSetCmd: simple local name, >255 locals} {
+    proc 260locals {} {
+        # create 260 locals (the last ones with index > 255)
+        set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
+        set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
+        set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
+        set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
+        set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
+        set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
+        set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
+        set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
+        set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
+        set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
+        set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
+        set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
+        set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
+        set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
+        set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
+        set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
+        set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
+        set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
+        set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
+        set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
+        set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
+        set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
+        set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
+        set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
+        set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
+        set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
+        set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
+        set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
+        set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
+        set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
+        set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
+        set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
+        set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
+        set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
+        set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
+        set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
+        set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
+        set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
+        set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
+        set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
+        set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
+        set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
+        set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
+        set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
+        set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
+        set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
+        set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
+        set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
+        set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
+        set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
+        set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
+        set z5 0; set z6 0; set z7 0; set z8 0; set z9 1234
+    }
+    260locals
+} {1234}
+
+test set-1.17 {TclCompileSetCmd: doing assignment, simple int} {
+    set i 5
+    set i 123
+} 123
+
+test set-1.18 {TclCompileSetCmd: doing assignment, simple int} {
+    set i 5
+    set i -100
+} -100
+
+test set-1.19 {TclCompileSetCmd: doing assignment, simple but not int} {
+    set i 5
+    set i 0x12MNOP
+    set i
+} {0x12MNOP}
+
+test set-1.20 {TclCompileSetCmd: doing assignment, in quotes} {
+    set i 25
+    set i "-100"
+} -100
+
+test set-1.21 {TclCompileSetCmd: doing assignment, in braces} {
+    set i 24
+    set i {126}
+} 126
+
+test set-1.22 {TclCompileSetCmd: doing assignment, large int} {
+    set i 5
+    set i 200000
+} 200000
+
+test set-1.23 {TclCompileSetCmd: doing assignment, formatted int != int} {
+    set i 25
+    set i 000012345     ;# a decimal literal == 5349 decimal
+    list $i [incr i]
+} {000012345 12346}
+
+################################################################################
+# LIST
+################################################################################
+
+test list-1.1 {basic tests} {list a b c} {a b c}
+test list-1.2 {basic tests} {list {a b} c} {{a b} c}
+test list-1.3 {basic tests} {list \{a b c} {\{a b c}
+test list-1.4 {basic tests} "list a{}} b{} c}" "a\\{\\}\\} b{} c\\}"
+test list-1.5 {basic tests} {list a\[ b\] } "{a\[} b\\]"
+test list-1.6 {basic tests} {list c\  d\t } "{c } {d\t}"
+test list-1.7 {basic tests} {list e\n f\$ } "{e\n} {f\$}"
+test list-1.8 {basic tests} {list g\; h\\} {{g;} h\\}
+test list-1.9 {basic tests} "list a\\\[} b\\\]} " "a\\\[\\\} b\\\]\\\}"
+test list-1.10 {basic tests} "list c\\\} d\\t} " "c\\} d\\t\\}"
+test list-1.11 {basic tests} "list e\\n} f\\$} " "e\\n\\} f\\$\\}"
+test list-1.12 {basic tests} "list g\\;} h\\\\} " "g\\;\\} {h\\}}"
+test list-1.13 {basic tests} {list a {{}} b} {a {{}} b}
+test list-1.14 {basic tests} {list a b xy\\} "a b xy\\\\"
+test list-1.15 {basic tests} "list a b\} e\\" "a b\\} e\\\\"
+test list-1.16 {basic tests} "list a b\}\\\$ e\\\$\\" "a b\\}\\\$ e\\\$\\\\"
+test list-1.17 {basic tests} {list a\f \{\f} "{a\f} \\\{\\f"
+test list-1.18 {basic tests} {list a\r \{\r} "{a\r} \\\{\\r"
+test list-1.19 {basic tests} {list a\v \{\v} "{a\v} \\\{\\v"
+test list-1.20 {basic tests} {list \"\}\{} "\\\"\\}\\{"
+test list-1.21 {basic tests} {list a b c\\\nd} "a b c\\\\\\nd"
+test list-1.22 {basic tests} {list "{ab}\\"} \\{ab\\}\\\\
+test list-1.23 {basic tests} {list \{} "\\{"
+test list-1.24 {basic tests} {list} {}
+
+set num 0
+proc lcheck {testid a b c} {
+    global num d
+    set d [list $a $b $c]
+    test ${testid}-0 {what goes in must come out} {lindex $d 0} $a
+    test ${testid}-1 {what goes in must come out} {lindex $d 1} $b
+    test ${testid}-2 {what goes in must come out} {lindex $d 2} $c
+}
+lcheck list-2.1  a b c
+lcheck list-2.2  "a b" c\td e\nf
+lcheck list-2.3  {{a b}} {} {  }
+lcheck list-2.4  \$ \$ab ab\$
+lcheck list-2.5  \; \;ab ab\;
+lcheck list-2.6  \[ \[ab ab\[
+lcheck list-2.7  \\ \\ab ab\\
+lcheck list-2.8  {"} {"ab} {ab"}        ;#" Stupid emacs highlighting!
+lcheck list-2.9  {a b} { ab} {ab }
+lcheck list-2.10 a{ a{b \{ab
+lcheck list-2.11 a} a}b }ab
+lcheck list-2.12 a\\} {a \}b} {a \{c}
+lcheck list-2.13 xyz \\ 1\\\n2
+lcheck list-2.14 "{ab}\\" "{ab}xy" abc
+
+concat {}
+
+################################################################################
+# WHILE
+################################################################################
+
+test while-1.9 {TclCompileWhileCmd: simple command body} {
+    set a {}
+    set i 1
+    while {$i<6} {
+        if $i==4 break
+        set a [concat $a $i]
+        incr i
+    }
+    set a
+} {1 2 3}
+
+test while-1.10 {TclCompileWhileCmd: command body in quotes} {
+    set a {}
+    set i 1
+    while {$i<6} "append a x; incr i"
+    set a
+} {xxxxx}
+
+test while-1.13 {TclCompileWhileCmd: while command result} {
+    set i 0
+    set a [while {$i < 5} {incr i}]
+    set a
+} {}
+
+test while-1.14 {TclCompileWhileCmd: while command result} {
+    set i 0
+    set a [while {$i < 5} {if $i==3 break; incr i}]
+    set a
+} {}
+
+test while-2.1 {continue tests} {
+    set a {}
+    set i 1
+    while {$i <= 4} {
+        incr i
+        if {$i == 3} continue
+        set a [concat $a $i]
+    }
+    set a
+} {2 4 5}
+test while-2.2 {continue tests} {
+    set a {}
+    set i 1
+    while {$i <= 4} {
+        incr i
+        if {$i != 2} continue
+        set a [concat $a $i]
+    }
+    set a
+} {2}
+test while-2.3 {continue tests, nested loops} {
+    set msg {}
+    set i 1
+    while {$i <= 4} {
+        incr i
+        set a 1
+        while {$a <= 2} {
+            incr a
+            if {$i>=3 && $a>=3} continue
+            set msg [concat $msg "$i.$a"]
+        }
+    }
+    set msg
+} {2.2 2.3 3.2 4.2 5.2}
+
+test while-4.1 {while and computed command names} {
+    set i 0
+    set z while
+    $z {$i < 10} {
+        incr i
+    }
+    set i
+} 10
+
+test while-5.2 {break tests with computed command names} {
+    set a {}
+    set i 1
+    set z break
+    while {$i <= 4} {
+        if {$i == 3} $z
+        set a [concat $a $i]
+        incr i
+    }
+    set a
+} {1 2}
+
+test while-7.1 {delayed substitution of body} {
+    set i 0
+    while {[incr i] < 10} "
+       set result $i
+    "
+    proc p {} {
+        set i 0
+        while {[incr i] < 10} "
+            set result $i
+        "
+        set result
+    }
+    append result [p]
+} {00}
+
+################################################################################
+# LSET
+################################################################################
+
+set lset lset
+
+test lset-2.1 {lset, not compiled, 3 args, second arg a plain index} {
+    set x {0 1 2}
+    list [eval [list $lset x 0 3]] $x
+} {{3 1 2} {3 1 2}}
+
+test lset-3.1 {lset, not compiled, 3 args, data duplicated} {
+    set x {0 1 2}
+    list [eval [list $lset x 0 $x]] $x
+} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
+
+test lset-3.2 {lset, not compiled, 3 args, data duplicated} {
+    set x {0 1}
+    set y $x
+    list [eval [list $lset x 0 2]] $x $y
+} {{2 1} {2 1} {0 1}}
+
+test lset-3.3 {lset, not compiled, 3 args, data duplicated} {
+    set x {0 1}
+    set y $x
+    list [eval [list $lset x 0 $x]] $x $y
+} {{{0 1} 1} {{0 1} 1} {0 1}}
+
+test lset-3.4 {lset, not compiled, 3 args, data duplicated} {
+    set x {0 1 2}
+    list [eval [list $lset x [list 0] $x]] $x
+} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
+
+test lset-3.5 {lset, not compiled, 3 args, data duplicated} {
+    set x {0 1}
+    set y $x
+    list [eval [list $lset x [list 0] 2]] $x $y
+} {{2 1} {2 1} {0 1}}
+
+test lset-3.6 {lset, not compiled, 3 args, data duplicated} {
+    set x {0 1}
+    set y $x
+    list [eval [list $lset x [list 0] $x]] $x $y
+} {{{0 1} 1} {{0 1} 1} {0 1}}
+
+test lset-4.2 {lset, not compiled, 3 args, bad index} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a [list 2a2] w]
+    } msg] $msg
+} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lset-4.3 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a [list -1] w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-4.4 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a [list 3] w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-4.5 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a [list end--1] w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-4.6 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a [list end-3] w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-4.8 {lset, not compiled, 3 args, bad index} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a 2a2 w]
+    } msg] $msg
+} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lset-4.9 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a -1 w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-4.10 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a 3 w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-4.11 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a end--1 w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-4.12 {lset, not compiled, 3 args, index out of range} {
+    set a {x y z}
+    list [catch {
+       eval [list $lset a end-3 w]
+    } msg] $msg
+} {1 {list index out of range}}
+
+test lset-6.1 {lset, not compiled, 3 args, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a 0 a]] $a
+} {{a y z} {a y z}}
+
+test lset-6.2 {lset, not compiled, 3 args, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a [list 0] a]] $a
+} {{a y z} {a y z}}
+
+test lset-6.3 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a 2 a]] $a
+} {{x y a} {x y a}}
+
+test lset-6.4 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a [list 2] a]] $a
+} {{x y a} {x y a}}
+
+test lset-6.5 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a end a]] $a
+} {{x y a} {x y a}}
+
+test lset-6.6 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a [list end] a]] $a
+} {{x y a} {x y a}}
+
+test lset-6.7 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a end-0 a]] $a
+} {{x y a} {x y a}}
+
+test lset-6.8 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a [list end-0] a]] $a
+} {{x y a} {x y a}}
+test lset-6.9 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a end-2 a]] $a
+} {{a y z} {a y z}}
+
+test lset-6.10 {lset, not compiled, 1-d list basics} {
+    set a {x y z}
+    list [eval [list $lset a [list end-2] a]] $a
+} {{a y z} {a y z}}
+
+test lset-7.1 {lset, not compiled, data sharing} {
+    set a 0
+    list [eval [list $lset a $a {gag me}]] $a
+} {{{gag me}} {{gag me}}}
+
+test lset-7.2 {lset, not compiled, data sharing} {
+    set a [list 0]
+    list [eval [list $lset a $a {gag me}]] $a
+} {{{gag me}} {{gag me}}}
+
+test lset-7.3 {lset, not compiled, data sharing} {
+    set a {x y}
+    list [eval [list $lset a 0 $a]] $a
+} {{{x y} y} {{x y} y}}
+
+test lset-7.4 {lset, not compiled, data sharing} {
+    set a {x y}
+    list [eval [list $lset a [list 0] $a]] $a
+} {{{x y} y} {{x y} y}}
+
+test lset-7.5 {lset, not compiled, data sharing} {
+    set n 0
+    set a {x y}
+    list [eval [list $lset a $n $n]] $a $n
+} {{0 y} {0 y} 0}
+
+test lset-7.6 {lset, not compiled, data sharing} {
+    set n [list 0]
+    set a {x y}
+    list [eval [list $lset a $n $n]] $a $n
+} {{0 y} {0 y} 0}
+
+test lset-7.7 {lset, not compiled, data sharing} {
+    set n 0
+    set a [list $n $n]
+    list [eval [list $lset a $n 1]] $a $n
+} {{1 0} {1 0} 0}
+
+test lset-7.8 {lset, not compiled, data sharing} {
+    set n [list 0]
+    set a [list $n $n]
+    list [eval [list $lset a $n 1]] $a $n
+} {{1 0} {1 0} 0}
+
+test lset-7.9 {lset, not compiled, data sharing} {
+    set a 0
+    list [eval [list $lset a $a $a]] $a
+} {0 0}
+
+test lset-7.10 {lset, not compiled, data sharing} {
+    set a [list 0]
+    list [eval [list $lset a $a $a]] $a
+} {0 0}
+
+test lset-8.3 {lset, not compiled, bad second index} {
+    set a {{b c} {d e}}
+    list [catch {eval [list $lset a 0 2a2 f]} msg] $msg
+} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lset-8.5 {lset, not compiled, second index out of range} {
+    set a {{b c} {d e} {f g}}
+    list [catch {eval [list $lset a 2 -1 h]} msg] $msg
+} {1 {list index out of range}}
+
+test lset-8.7 {lset, not compiled, second index out of range} {
+    set a {{b c} {d e} {f g}}
+    list [catch {eval [list $lset a 2 2 h]} msg] $msg
+} {1 {list index out of range}}
+
+test lset-8.9 {lset, not compiled, second index out of range} {
+    set a {{b c} {d e} {f g}}
+    list [catch {eval [list $lset a 2 end--1 h]} msg] $msg
+} {1 {list index out of range}}
+
+test lset-8.11 {lset, not compiled, second index out of range} {
+    set a {{b c} {d e} {f g}}
+    list [catch {eval [list $lset a 2 end-2 h]} msg] $msg
+} {1 {list index out of range}}
+
+test lset-9.1 {lset, not compiled, entire variable} {
+    set a x
+    list [eval [list $lset a y]] $a
+} {y y}
+
+test lset-10.1 {lset, not compiled, shared data} {
+    set row {p q}
+    set a [list $row $row]
+    list [eval [list $lset a 0 0 x]] $a
+} {{{x q} {p q}} {{x q} {p q}}}
+
+test lset-11.1 {lset, not compiled, 2-d basics} {
+    set a {{b c} {d e}}
+    list [eval [list $lset a 0 0 f]] $a
+} {{{f c} {d e}} {{f c} {d e}}}
+
+test lset-11.3 {lset, not compiled, 2-d basics} {
+    set a {{b c} {d e}}
+    list [eval [list $lset a 0 1 f]] $a
+} {{{b f} {d e}} {{b f} {d e}}}
+
+test lset-11.5 {lset, not compiled, 2-d basics} {
+    set a {{b c} {d e}}
+    list [eval [list $lset a 1 0 f]] $a
+} {{{b c} {f e}} {{b c} {f e}}}
+
+test lset-11.7 {lset, not compiled, 2-d basics} {
+    set a {{b c} {d e}}
+    list [eval [list $lset a 1 1 f]] $a
+} {{{b c} {d f}} {{b c} {d f}}}
+
+test lset-12.0 {lset, not compiled, typical sharing pattern} {
+    set zero 0
+    set row [list $zero $zero $zero $zero]
+    set ident [list $row $row $row $row]
+    for { set i 0 } { $i < 4 } { incr i } {
+       eval [list $lset ident $i $i 1]
+    }
+    set ident
+} {{1 0 0 0} {0 1 0 0} {0 0 1 0} {0 0 0 1}}
+
+test lset-13.0 {lset, not compiled, shimmering hell} {
+    set a 0
+    list [eval [list $lset a $a $a $a $a {gag me}]] $a
+} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
+
+test lset-13.1 {lset, not compiled, shimmering hell} {
+    set a [list 0]
+    list [eval [list $lset a $a $a $a $a {gag me}]] $a
+} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
+
+test lset-14.1 {lset, not compiled, list args, is string rep preserved?} {
+    set a { { 1 2 } { 3 4 } }
+    catch { eval [list $lset a {1 5} 5] }
+    list $a [lindex $a 1]
+} "{ { 1 2 } { 3 4 } } { 3 4 }"
+
+catch {unset noRead}
+catch {unset noWrite}
+catch {rename failTrace {}}
+catch {unset ::x}
+catch {unset ::y}
+
+################################################################################
+# IF
+################################################################################
+
+test if-1.1 {bad syntax: lacking all} {
+       catch {if}
+} 1
+test if-1.2 {bad syntax: lacking then-clause} {
+       catch {if 1==1}
+} 1
+test if-1.3 {bad syntax: lacking then-clause 2} {
+       catch {if 1==1 then}
+} 1
+test if-1.4 {bad syntax: lacking else-clause after keyword 'else'} {
+       catch {if 1==0 then {list 1} else}
+} 1
+test if-1.5 {bad syntax: lacking expr after 'elseif'} {
+       catch {if 1==0 then {list 1} elseif}
+} 1
+test if-1.6 {bad syntax: lacking then-clause after 'elseif'} {
+       catch {if 1==0 then {list 1} elseif 1==1}
+} 1
+test if-1.7 {bad syntax: lacking else-clause after 'elseif' after keyword 'else'} {
+       catch {if 1==0 then {list 1} elseif 1==0 {list 2} else}
+} 1
+test if-1.8 {bad syntax: extra arg after implicit else-clause} {
+       catch {if 1==0 {list 1} elseif 1==0 then {list 2} {list 3} else}
+} 1
+test if-1.9 {bad syntax: elsif-clause after else-clause} {
+       catch {if 1==0 {list 1} else {list 2} elseif 1==1 {list 3}}
+} 1
+test if-2.1 {taking proper branch} {
+    set a {}
+    if 0 {set a 1} else {set a 2}
+    set a
+} 2
+test if-2.2 {taking proper branch} {
+    set a {}
+    if 1 {set a 1} else {set a 2}
+    set a
+} 1
+test if-2.3 {taking proper branch} {
+    set a {}
+    if 1<2 {set a 1}
+    set a
+} 1
+test if-2.4 {taking proper branch} {
+    set a {}
+    if 1>2 {set a 1}
+    set a
+} {}
+test if-2.5 {taking proper branch} {
+    set a {}
+    if 0 {set a 1} else {}
+    set a
+} {}
+test if-2.6 {taking proper branch} {
+    set a {}
+    if 0 {set a 1} elseif 1 {set a 2} elseif 1 {set a 3} else {set a 4}
+    set a
+} 2
+test if-2.7 {taking proper branch} {
+    set a {}
+    if 0 {set a 1} elseif 0 {set a 2} elseif 1 {set a 3} else {set a 4}
+    set a
+} 3
+test if-2.8 {taking proper branch} {
+    set a {}
+    if 0 {set a 1} elseif 0 {set a 2} elseif 0 {set a 3} else {set a 4}
+    set a
+} 4
+test if-2.9 {taking proper branch, multiline test expr} {
+    set a {}
+    if {1 != \
+            3} {set a 3} else {set a 4}
+    set a
+} 3
+test if-3.1 {optional then-else args} {
+    set a 44
+    if 0 then {set a 1} elseif 0 then {set a 3} else {set a 2}
+    set a
+} 2
+test if-3.2 {optional then-else args} {
+    set a 44
+    if 1 then {set a 1} else {set a 2}
+    set a
+} 1
+test if-3.3 {optional then-else args} {
+    set a 44
+    if 0 {set a 1} else {set a 2}
+    set a
+} 2
+test if-3.4 {optional then-else args} {
+    set a 44
+    if 1 {set a 1} else {set a 2}
+    set a
+} 1
+test if-3.5 {optional then-else args} {
+    set a 44
+    if 0 then {set a 1} {set a 2}
+    set a
+} 2
+test if-3.6 {optional then-else args} {
+    set a 44
+    if 1 then {set a 1} {set a 2}
+    set a
+} 1
+test if-3.7 {optional then-else args} {
+    set a 44
+    if 0 then {set a 1} else {set a 2}
+    set a
+} 2
+test if-3.8 {optional then-else args} {
+    set a 44
+    if 0 then {set a 1} elseif 0 {set a 2} elseif 0 {set a 3} {set a 4}
+    set a
+} 4
+test if-4.1 {return value} {
+    if 1 then {set a 22; concat abc}
+} abc
+test if-4.2 {return value} {
+    if 0 then {set a 22; concat abc} elseif 1 {concat def} {concat ghi}
+} def
+test if-4.3 {return value} {
+    if 0 then {set a 22; concat abc} else {concat def}
+} def
+test if-4.4 {return value} {
+    if 0 then {set a 22; concat abc}
+} {}
+test if-4.5 {return value} {
+    if 0 then {set a 22; concat abc} elseif 0 {concat def}
+} {}
+test if-5.1 {error conditions} {
+    list [catch {if {[error "error in condition"]} foo} msg] $msg
+} {1 {error in condition}}
+test if-5.2 {error conditions} {
+    list [catch {if 2 the} msg] $msg
+} {1 {invalid command name "the"}}
+test if-5.3 {error conditions} {
+    list [catch {if 2 then {[error "error in then clause"]}} msg] $msg
+} {1 {error in then clause}}
+test if-5.4 {error conditions} {
+    list [catch {if 0 then foo elsei} msg] $msg
+} {1 {invalid command name "elsei"}}
+test if-5.5 {error conditions} {
+    list [catch {if 0 then foo elseif 0 bar els} msg] $msg
+} {1 {invalid command name "els"}}
+test if-5.6 {error conditions} {
+    list [catch {if 0 then foo elseif 0 bar else {[error "error in else clause"]}} msg] $msg
+} {1 {error in else clause}}
+
+################################################################################
+# APPEND
+################################################################################
+
+catch {unset x}
+
+test append-1.1 {append command} {
+    catch {unset x}
+    list [append x 1 2 abc "long string"] $x
+} {{12abclong string} {12abclong string}}
+test append-1.2 {append command} {
+    set x ""
+    list [append x first] [append x second] [append x third] $x
+} {first firstsecond firstsecondthird firstsecondthird}
+test append-1.3 {append command} {
+    set x "abcd"
+    append x
+} abcd
+
+test append-2.1 {long appends} {
+    set x ""
+    for {set i 0} {$i < 1000} {set i [expr $i+1]} {
+       append x "foobar "
+    }
+    set y "foobar"
+    set y "$y $y $y $y $y $y $y $y $y $y"
+    set y "$y $y $y $y $y $y $y $y $y $y"
+    set y "$y $y $y $y $y $y $y $y $y $y "
+    expr {$x eq $y}
+} 1
+
+test append-3.1 {append errors} {
+    list [catch {append} msg] $msg
+} {1 {wrong # args: should be "append varName ?value value ...?"}}
+test append-3.2 {append errors} {
+    set x 1
+    list [catch {append x(0) 44} msg] $msg
+} {1 {can't set "x(0)": variable isn't array}}
+test append-3.3 {append errors} {
+    catch {unset x}
+    list [catch {append x} msg] $msg
+} {1 {can't read "x": no such variable}}
+
+test append-4.1 {lappend command} {
+    catch {unset x}
+    list [lappend x 1 2 abc "long string"] $x
+} {{1 2 abc {long string}} {1 2 abc {long string}}}
+test append-4.2 {lappend command} {
+    set x ""
+    list [lappend x first] [lappend x second] [lappend x third] $x
+} {first {first second} {first second third} {first second third}}
+test append-4.3 {lappend command} {
+    proc foo {} {
+       global x
+       set x old
+       unset x
+       lappend x new
+    }
+    set result [foo]
+    rename foo {}
+    set result
+} {new}
+test append-4.4 {lappend command} {
+    set x {}
+    lappend x \{\  abc
+} {\{\  abc}
+test append-4.5 {lappend command} {
+    set x {}
+    lappend x \{ abc
+} {\{ abc}
+test append-4.6 {lappend command} {
+    set x {1 2 3}
+    lappend x
+} {1 2 3}
+test append-4.7 {lappend command} {
+    set x "a\{"
+    lappend x abc
+} "a\\\{ abc"
+test append-4.8 {lappend command} {
+    set x "\\\{"
+    lappend x abc
+} "\\{ abc"
+#test append-4.9 {lappend command} {
+#    set x " \{"
+#    list [catch {lappend x abc} msg] $msg
+#} {1 {unmatched open brace in list}}
+#test append-4.10 {lappend command} {
+#    set x "   \{"
+#    list [catch {lappend x abc} msg] $msg
+#} {1 {unmatched open brace in list}}
+#test append-4.11 {lappend command} {
+#    set x "\{\{\{"
+#    list [catch {lappend x abc} msg] $msg
+#} {1 {unmatched open brace in list}}
+#test append-4.12 {lappend command} {
+#    set x "x \{\{\{"
+#    list [catch {lappend x abc} msg] $msg
+#} {1 {unmatched open brace in list}}
+test append-4.13 {lappend command} {
+    set x "x\{\{\{"
+    lappend x abc
+} "x\\\{\\\{\\\{ abc"
+test append-4.14 {lappend command} {
+    set x " "
+    lappend x abc
+} "abc"
+test append-4.15 {lappend command} {
+    set x "\\ "
+    lappend x abc
+} "{ } abc"
+test append-4.16 {lappend command} {
+    set x "x "
+    lappend x abc
+} "x abc"
+test append-4.17 {lappend command} {
+    catch {unset x}
+    lappend x
+} {}
+test append-4.18 {lappend command} {
+    catch {unset x}
+    lappend x {}
+} {{}}
+test append-4.19 {lappend command} {
+    catch {unset x}
+    lappend x(0)
+} {}
+test append-4.20 {lappend command} {
+    catch {unset x}
+    lappend x(0) abc
+} {abc}
+
+proc check {var size} {
+    set l [llength $var]
+    if {$l != $size} {
+       return "length mismatch: should have been $size, was $l"
+    }
+    for {set i 0} {$i < $size} {set i [expr $i+1]} {
+       set j [lindex $var $i]
+       if {$j ne "item $i"} {
+           return "element $i should have been \"item $i\", was \"$j\""
+       }
+    }
+    return ok
+}
+test append-5.1 {long lappends} {
+    catch {unset x}
+    set x ""
+    for {set i 0} {$i < 300} {set i [expr $i+1]} {
+       lappend x "item $i"
+    }
+    check $x 300
+} ok
+
+test append-6.1 {lappend errors} {
+    list [catch {lappend} msg] $msg
+} {1 {wrong # args: should be "lappend varName ?value value ...?"}}
+test append-6.2 {lappend errors} {
+    set x 1
+    list [catch {lappend x(0) 44} msg] $msg
+} {1 {can't set "x(0)": variable isn't array}}
+
+################################################################################
+# UPLEVEL
+################################################################################
+
+proc a {x y} {
+    newset z [expr $x+$y]
+    return $z
+}
+proc newset {name value} {
+    uplevel set $name $value
+    uplevel 1 {uplevel 1 {set xyz 22}}
+}
+
+test uplevel-1.1 {simple operation} {
+    set xyz 0
+    a 22 33
+} 55
+test uplevel-1.2 {command is another uplevel command} {
+    set xyz 0
+    a 22 33
+    set xyz
+} 22
+
+proc a1 {} {
+    b1
+    global a a1
+    set a $x
+    set a1 $y
+}
+proc b1 {} {
+    c1
+    global b b1
+    set b $x
+    set b1 $y
+}
+proc c1 {} {
+    uplevel 1 set x 111
+    uplevel #2 set y 222
+    uplevel 2 set x 333
+    uplevel #1 set y 444
+    uplevel 3 set x 555
+    uplevel #0 set y 666
+}
+a1
+test uplevel-2.1 {relative and absolute uplevel} {set a} 333
+test uplevel-2.2 {relative and absolute uplevel} {set a1} 444
+test uplevel-2.3 {relative and absolute uplevel} {set b} 111
+test uplevel-2.4 {relative and absolute uplevel} {set b1} 222
+test uplevel-2.5 {relative and absolute uplevel} {set x} 555
+test uplevel-2.6 {relative and absolute uplevel} {set y} 666
+
+test uplevel-3.1 {uplevel to same level} {
+    set x 33
+    uplevel #0 set x 44
+    set x
+} 44
+test uplevel-3.2 {uplevel to same level} {
+    set x 33
+    uplevel 0 set x
+} 33
+test uplevel-3.3 {uplevel to same level} {
+    set y xxx
+    proc a1 {} {set y 55; uplevel 0 set y 66; return $y}
+    a1
+} 66
+test uplevel-3.4 {uplevel to same level} {
+    set y zzz
+    proc a1 {} {set y 55; uplevel #1 set y}
+    a1
+} 55
+
+test uplevel-4.1 {error: non-existent level} {
+    list [catch c1 msg] $msg
+} {1 {bad level "#2"}}
+test uplevel-4.2 {error: non-existent level} {
+    proc c2 {} {uplevel 3 {set a b}}
+    list [catch c2 msg] $msg
+} {1 {bad level "3"}}
+test uplevel-4.3 {error: not enough args} {
+    list [catch uplevel msg] $msg
+} {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}}
+test uplevel-4.4 {error: not enough args} {
+    proc upBug {} {uplevel 1}
+    list [catch upBug msg] $msg
+} {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}}
+
+proc a2 {} {
+    uplevel a3
+}
+proc a3 {} {
+    global x y
+    set x [info level]
+    set y [info level 1]
+}
+a2
+test uplevel-5.1 {info level} {set x} 1
+test uplevel-5.2 {info level} {set y} a3
+
+################################################################################
+# UNKNOWN
+################################################################################
+
+catch {unset x}
+catch {rename unknown unknown.old}
+
+test unknown-1.1 {non-existent "unknown" command} {
+    list [catch {_non-existent_ foo bar} msg] $msg
+} {1 {invalid command name "_non-existent_"}}
+
+proc unknown {args} {
+    global x
+    set x $args
+}
+
+test unknown-2.1 {calling "unknown" command} {
+    foobar x y z
+    set x
+} {foobar x y z}
+test unknown-2.2 {calling "unknown" command with lots of args} {
+    foobar 1 2 3 4 5 6 7
+    set x
+} {foobar 1 2 3 4 5 6 7}
+test unknown-2.3 {calling "unknown" command with lots of args} {
+    foobar 1 2 3 4 5 6 7 8
+    set x
+} {foobar 1 2 3 4 5 6 7 8}
+test unknown-2.4 {calling "unknown" command with lots of args} {
+    foobar 1 2 3 4 5 6 7 8 9
+    set x
+} {foobar 1 2 3 4 5 6 7 8 9}
+
+test unknown-3.1 {argument quoting in calls to "unknown"} {
+    foobar \{ \} a\{b \; "\\" \$a a\[b \]
+    set x
+} "foobar \\{ \\} a\\{b {;} \\\\ {\$a} {a\[b} \\]"
+
+proc unknown args {
+    error "unknown failed"
+}
+
+test unknown-4.1 {errors in "unknown" procedure} {
+    list [catch {non-existent a b} msg] $msg
+} {1 {unknown failed}}
+
+rename unknown {}
+
+################################################################################
+# INCR
+################################################################################
+
+catch {unset x}
+catch {unset i}
+
+test incr-1.1 {TclCompileIncrCmd: missing variable name} {
+    list [catch {incr} msg] $msg
+} {1 {wrong # args: should be "incr varName ?increment?"}}
+test incr-1.2 {TclCompileIncrCmd: simple variable name} {
+    set i 10
+    list [incr i] $i
+} {11 11}
+#test incr-1.3 {TclCompileIncrCmd: error compiling variable name} {
+#    set i 10
+#    catch {incr "i"xxx} msg
+#    set msg
+#} {extra characters after close-quote}
+test incr-1.4 {TclCompileIncrCmd: simple variable name in quotes} {
+    set i 17
+    list [incr "i"] $i
+} {18 18}
+test incr-1.5 {TclCompileIncrCmd: simple variable name in braces} {
+    catch {unset {a simple var}}
+    set {a simple var} 27
+    list [incr {a simple var}] ${a simple var}
+} {28 28}
+test incr-1.6 {TclCompileIncrCmd: simple array variable name} {
+    catch {unset a}
+    set a(foo) 37
+    list [incr a(foo)] $a(foo)
+} {38 38}
+test incr-1.7 {TclCompileIncrCmd: non-simple (computed) variable name} {
+    set x "i"
+    set i 77
+    list [incr $x 2] $i
+} {79 79}
+test incr-1.8 {TclCompileIncrCmd: non-simple (computed) variable name} {
+    set x "i"
+    set i 77
+    list [incr [set x] +2] $i
+} {79 79}
+
+test incr-1.9 {TclCompileIncrCmd: increment given} {
+    set i 10
+    list [incr i +07] $i
+} {17 17}
+test incr-1.10 {TclCompileIncrCmd: no increment given} {
+    set i 10
+    list [incr i] $i
+} {11 11}
+
+test incr-1.11 {TclCompileIncrCmd: simple global name} {
+    proc p {} {
+        global i
+        set i 54
+        incr i
+    }
+    p
+} {55}
+test incr-1.12 {TclCompileIncrCmd: simple local name} {
+    proc p {} {
+        set foo 100
+        incr foo
+    }
+    p
+} {101}
+test incr-1.13 {TclCompileIncrCmd: simple but new (unknown) local name} {
+    proc p {} {
+        incr bar
+    }
+    catch {p} msg
+    set msg
+} {1}
+test incr-1.14 {TclCompileIncrCmd: simple local name, >255 locals} {
+    proc 260locals {} {
+        # create 260 locals
+        set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
+        set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
+        set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
+        set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
+        set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
+        set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
+        set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
+        set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
+        set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
+        set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
+        set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
+        set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
+        set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
+        set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
+        set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
+        set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
+        set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
+        set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
+        set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
+        set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
+        set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
+        set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
+        set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
+        set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
+        set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
+        set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
+        set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
+        set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
+        set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
+        set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
+        set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
+        set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
+        set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
+        set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
+        set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
+        set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
+        set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
+        set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
+        set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
+        set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
+        set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
+        set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
+        set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
+        set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
+        set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
+        set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
+        set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
+        set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
+        set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
+        set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
+        set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
+        set z5 0; set z6 0; set z7 0; set z8 0; set z9 0
+        # now increment the last one (local var index > 255)
+        incr z9
+    }
+    260locals
+} {1}
+test incr-1.15 {TclCompileIncrCmd: variable is array} {
+    catch {unset a}
+    set a(foo) 27
+    set x [incr a(foo) 11]
+    catch {unset a}
+    set x
+} 38
+test incr-1.16 {TclCompileIncrCmd: variable is array, elem substitutions} {
+    catch {unset a}
+    set i 5
+    set a(foo5) 27
+    set x [incr a(foo$i) 11]
+    catch {unset a}
+    set x
+} 38
+
+test incr-1.17 {TclCompileIncrCmd: increment given, simple int} {
+    set i 5
+    incr i 123
+} 128
+test incr-1.18 {TclCompileIncrCmd: increment given, simple int} {
+    set i 5
+    incr i -100
+} -95
+#test incr-1.19 {TclCompileIncrCmd: increment given, but erroneous} {
+#    set i 5
+#    catch {incr i [set]} msg
+#    set errorInfo
+#} {wrong # args: should be "set varName ?newValue?"
+#    while compiling
+#"set"
+#    while compiling
+#"incr i [set]"}
+test incr-1.20 {TclCompileIncrCmd: increment given, in quotes} {
+    set i 25
+    incr i "-100"
+} -75
+test incr-1.21 {TclCompileIncrCmd: increment given, in braces} {
+    set i 24
+    incr i {126}
+} 150
+test incr-1.22 {TclCompileIncrCmd: increment given, large int} {
+    set i 5
+    incr i 200000
+} 200005
+test incr-1.23 {TclCompileIncrCmd: increment given, formatted int != int} {
+    set i 25
+    incr i 000012345     ;# a decimal literal
+} 12370
+test incr-1.24 {TclCompileIncrCmd: increment given, formatted int != int} {
+    set i 25
+    catch {incr i 1a} msg
+    set msg
+} {expected integer but got "1a"}
+
+test incr-1.25 {TclCompileIncrCmd: too many arguments} {
+    set i 10
+    catch {incr i 10 20} msg
+    set msg
+} {wrong # args: should be "incr varName ?increment?"}
+
+
+test incr-1.29 {TclCompileIncrCmd: runtime error, bad variable value} {
+    set x "  -  "
+    list [catch {incr x 1} msg] $msg
+} {1 {expected integer but got "  -  "}}
+
+test incr-1.30 {TclCompileIncrCmd: array var, braced (no subs)} {
+    catch {unset array}
+    set array(\$foo) 4
+    incr {array($foo)}
+} 5
+    
+# Check "incr" and computed command names.
+
+test incr-2.0 {incr and computed command names} {
+    set i 5
+    set z incr
+    $z i -1
+    set i
+} 4
+catch {unset x}
+catch {unset i}
+
+test incr-2.1 {incr command (not compiled): missing variable name} {
+    set z incr
+    list [catch {$z} msg] $msg
+} {1 {wrong # args: should be "incr varName ?increment?"}}
+test incr-2.2 {incr command (not compiled): simple variable name} {
+    set z incr
+    set i 10
+    list [$z i] $i
+} {11 11}
+test incr-2.4 {incr command (not compiled): simple variable name in quotes} {
+    set z incr
+    set i 17
+    list [$z "i"] $i
+} {18 18}
+test incr-2.5 {incr command (not compiled): simple variable name in braces} {
+    set z incr
+    catch {unset {a simple var}}
+    set {a simple var} 27
+    list [$z {a simple var}] ${a simple var}
+} {28 28}
+test incr-2.6 {incr command (not compiled): simple array variable name} {
+    set z incr
+    catch {unset a}
+    set a(foo) 37
+    list [$z a(foo)] $a(foo)
+} {38 38}
+test incr-2.7 {incr command (not compiled): non-simple (computed) variable name} {
+    set z incr
+    set x "i"
+    set i 77
+    list [$z $x 2] $i
+} {79 79}
+test incr-2.8 {incr command (not compiled): non-simple (computed) variable name} {
+    set z incr
+    set x "i"
+    set i 77
+    list [$z [set x] +2] $i
+} {79 79}
+
+test incr-2.9 {incr command (not compiled): increment given} {
+    set z incr
+    set i 10
+    list [$z i +07] $i
+} {17 17}
+test incr-2.10 {incr command (not compiled): no increment given} {
+    set z incr
+    set i 10
+    list [$z i] $i
+} {11 11}
+
+test incr-2.11 {incr command (not compiled): simple global name} {
+    proc p {} {
+       set z incr
+        global i
+        set i 54
+        $z i
+    }
+    p
+} {55}
+test incr-2.12 {incr command (not compiled): simple local name} {
+    proc p {} {
+       set z incr
+        set foo 100
+        $z foo
+    }
+    p
+} {101}
+test incr-2.13 {incr command (not compiled): simple but new (unknown) local name} {
+    proc p {} {
+       set z incr
+        $z bar
+    }
+    catch {p} msg
+    set msg
+} {1}
+test incr-2.14 {incr command (not compiled): simple local name, >255 locals} {
+   proc 260locals {} {
+        set z incr
+        # create 260 locals
+        set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
+        set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
+        set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
+        set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
+        set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
+        set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
+        set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
+        set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
+        set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
+        set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
+        set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
+        set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
+        set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
+        set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
+        set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
+        set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
+        set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
+        set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
+        set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
+        set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
+        set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
+        set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
+        set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
+        set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
+        set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
+        set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
+        set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
+        set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
+        set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
+        set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
+        set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
+        set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
+        set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
+        set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
+        set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
+        set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
+        set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
+        set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
+        set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
+        set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
+        set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
+        set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
+        set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
+        set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
+        set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
+        set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
+        set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
+        set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
+        set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
+        set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
+        set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
+        set z5 0; set z6 0; set z7 0; set z8 0; set z9 0
+        # now increment the last one (local var index > 255)
+        $z z9
+    }
+    260locals
+} {1}
+test incr-2.15 {incr command (not compiled): variable is array} {
+    set z incr
+    catch {unset a}
+    set a(foo) 27
+    set x [$z a(foo) 11]
+    catch {unset a}
+    set x
+} 38
+test incr-2.16 {incr command (not compiled): variable is array, elem substitutions} {
+    set z incr
+    catch {unset a}
+    set i 5
+    set a(foo5) 27
+    set x [$z a(foo$i) 11]
+    catch {unset a}
+    set x
+} 38
+
+test incr-2.17 {incr command (not compiled): increment given, simple int} {
+    set z incr
+    set i 5
+    $z i 123
+} 128
+test incr-2.18 {incr command (not compiled): increment given, simple int} {
+    set z incr
+    set i 5
+    $z i -100
+} -95
+test incr-2.20 {incr command (not compiled): increment given, in quotes} {
+    set z incr
+    set i 25
+    $z i "-100"
+} -75
+test incr-2.21 {incr command (not compiled): increment given, in braces} {
+    set z incr
+    set i 24
+    $z i {126}
+} 150
+test incr-2.22 {incr command (not compiled): increment given, large int} {
+    set z incr
+    set i 5
+    $z i 200000
+} 200005
+test incr-2.23 {incr command (not compiled): increment given, formatted int != int} {
+    set z incr
+    set i 25
+    $z i 000012345     ;# an octal literal
+} 12370
+test incr-2.24 {incr command (not compiled): increment given, formatted int != int} {
+    set z incr
+    set i 25
+    catch {$z i 1a} msg
+    set msg
+} {expected integer but got "1a"}
+
+test incr-2.25 {incr command (not compiled): too many arguments} {
+    set z incr
+    set i 10
+    catch {$z i 10 20} msg
+    set msg
+} {wrong # args: should be "incr varName ?increment?"}
+
+test incr-2.29 {incr command (not compiled): runtime error, bad variable value} {
+    set z incr
+    set x "  -  "
+    list [catch {$z x 1} msg] $msg
+} {1 {expected integer but got "  -  "}}
+
+################################################################################
+# LLENGTH
+################################################################################
+
+test llength-1.1 {length of list} {
+    llength {a b c d}
+} 4
+test llength-1.2 {length of list} {
+    llength {a b c {a b {c d}} d}
+} 5
+test llength-1.3 {length of list} {
+    llength {}
+} 0
+
+test llength-2.1 {error conditions} {
+    list [catch {llength} msg] $msg
+} {1 {wrong # args: should be "llength list"}}
+test llength-2.2 {error conditions} {
+    list [catch {llength 123 2} msg] $msg
+} {1 {wrong # args: should be "llength list"}}
+
+################################################################################
+# LINDEX
+################################################################################
+
+set lindex lindex
+set minus -
+
+# Tests of Tcl_LindexObjCmd, NOT COMPILED
+
+test lindex-1.1 {wrong # args} {
+    list [catch {eval $lindex} result] $result
+} "1 {wrong # args: should be \"lindex list ?index ...?\"}"
+
+# Indices that are lists or convertible to lists
+
+#test lindex-2.1 {empty index list} {
+#    set x {}
+#    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+#} {{a b c} {a b c}}
+
+test lindex-2.2 {singleton index list} {
+    set x { 1 }
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {b b}
+
+test lindex-2.4 {malformed index list} {
+    set x \{
+    list [catch { eval [list $lindex {a b c} $x] } result] $result
+} {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?}
+
+# Indices that are integers or convertible to integers
+
+test lindex-3.1 {integer -1} {
+    set x ${minus}1
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {{} {}}
+
+test lindex-3.2 {integer 0} {
+    set x [string range 00 0 0]
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {a a}
+
+test lindex-3.3 {integer 2} {
+    set x [string range 22 0 0]
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {c c}
+
+test lindex-3.4 {integer 3} {
+    set x [string range 33 0 0]
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {{} {}}
+
+test lindex-3.7 {indexes don't shimmer wide ints} {
+    set x [expr {(1<<31) - 2}]
+    list $x [lindex {1 2 3} $x] [incr x] [incr x]
+} {2147483646 {} 2147483647 2147483648}
+
+# Indices relative to end
+
+test lindex-4.1 {index = end} {
+    set x end
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {c c}
+
+test lindex-4.2 {index = end--1} {
+    set x end--1
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {{} {}}
+
+test lindex-4.3 {index = end-0} {
+    set x end-0
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {c c}
+
+test lindex-4.4 {index = end-2} {
+    set x end-2
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {a a}
+
+test lindex-4.5 {index = end-3} {
+    set x end-3
+    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+} {{} {}}
+
+test lindex-4.8 {bad integer, not octal} {
+    set x end-0a2
+    list [catch { eval [list $lindex {a b c} $x] } result] $result
+} {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}}
+
+#test lindex-4.9 {incomplete end} {
+#    set x en
+#    list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+#} {c c}
+
+test lindex-4.10 {incomplete end-} {
+    set x end-
+    list [catch { eval [list $lindex {a b c} $x] } result] $result
+} {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lindex-5.1 {bad second index} {
+    list [catch { eval [list $lindex {a b c} 0 0a2] } result] $result
+} {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lindex-5.2 {good second index} {
+    eval [list $lindex {{a b c} {d e f} {g h i}} 1 2]
+} f
+
+test lindex-5.3 {three indices} {
+    eval [list $lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1]
+} f
+
+test lindex-7.1 {quoted elements} {
+    eval [list $lindex {a "b c" d} 1]
+} {b c}
+test lindex-7.2 {quoted elements} {
+    eval [list $lindex {"{}" b c} 0]
+} {{}}
+test lindex-7.3 {quoted elements} {
+    eval [list $lindex {ab "c d \" x" y} 1]
+} {c d " x}
+test lindex-7.4 {quoted elements} {
+    lindex {a b {c d "e} {f g"}} 2
+} {c d "e}
+
+test lindex-8.1 {data reuse} {
+    set x 0
+    eval [list $lindex $x $x]
+} {0}
+
+test lindex-8.2 {data reuse} {
+    set a 0
+    eval [list $lindex $a $a $a]
+} 0
+test lindex-8.3 {data reuse} {
+    set a 1
+    eval [list $lindex $a $a $a]
+} {}
+
+#----------------------------------------------------------------------
+
+test lindex-10.2 {singleton index list} {
+    set x { 1 }
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {b b}
+
+test lindex-10.4 {malformed index list} {
+    set x \{
+    list [catch { lindex {a b c} $x } result] $result
+} {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?}
+
+# Indices that are integers or convertible to integers
+
+test lindex-11.1 {integer -1} {
+    set x ${minus}1
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {{} {}}
+
+test lindex-11.2 {integer 0} {
+    set x [string range 00 0 0]
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {a a}
+
+test lindex-11.3 {integer 2} {
+    set x [string range 22 0 0]
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {c c}
+
+test lindex-11.4 {integer 3} {
+    set x [string range 33 0 0]
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {{} {}}
+
+# Indices relative to end
+test lindex-12.1 {index = end} {
+    set x end
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {c c}
+
+test lindex-12.2 {index = end--1} {
+    set x end--1
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {{} {}}
+
+test lindex-12.3 {index = end-0} {
+    set x end-0
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {c c}
+
+test lindex-12.4 {index = end-2} {
+    set x end-2
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {a a}
+
+test lindex-12.5 {index = end-3} {
+    set x end-3
+    catch {
+       list [lindex {a b c} $x] [lindex {a b c} $x]
+    } result
+    set result
+} {{} {}}
+
+test lindex-12.8 {bad integer, not octal} {
+    set x end-0a2
+    list [catch { lindex {a b c} $x } result] $result
+} {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lindex-12.10 {incomplete end-} {
+    set x end-
+    list [catch { lindex {a b c} $x } result] $result
+} {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lindex-13.1 {bad second index} {
+    list [catch { lindex {a b c} 0 0a2 } result] $result
+} {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lindex-13.2 {good second index} {
+    catch {
+       lindex {{a b c} {d e f} {g h i}} 1 2
+    } result
+    set result
+} f
+
+test lindex-13.3 {three indices} {
+    catch {
+       lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1
+    } result
+    set result
+} f
+
+test lindex-15.1 {quoted elements} {
+    catch {
+       lindex {a "b c" d} 1
+    } result
+    set result
+} {b c}
+test lindex-15.2 {quoted elements} {
+    catch {
+       lindex {"{}" b c} 0
+    } result
+    set result
+} {{}}
+test lindex-15.3 {quoted elements} {
+    catch {
+       lindex {ab "c d \" x" y} 1
+    } result
+    set result
+} {c d " x}
+test lindex-15.4 {quoted elements} {
+    catch {
+       lindex {a b {c d "e} {f g"}} 2
+    } result
+    set result
+} {c d "e}
+
+test lindex-16.1 {data reuse} {
+    set x 0
+    catch {
+       lindex $x $x
+    } result
+    set result
+} {0}
+
+test lindex-16.2 {data reuse} {
+    set a 0
+    catch {
+       lindex $a $a $a
+    } result
+    set result
+} 0
+test lindex-16.3 {data reuse} {
+    set a 1
+    catch {
+       lindex $a $a $a
+    } result
+    set result
+} {}
+
+test lindex-17.1 {no index} {
+    lindex {a b c}
+} {a b c}
+
+catch { unset lindex}
+catch { unset minus }
+
+################################################################################
+# LINDEX
+################################################################################
+
+catch {unset a}
+catch {unset x}
+
+# Basic "foreach" operation.
+
+test foreach-1.1 {basic foreach tests} {
+       set a {}
+       foreach i {a b c d} {
+               set a [concat $a $i]
+       }
+       set a
+} {a b c d}
+test foreach-1.2 {basic foreach tests} {
+  set a {}
+  foreach i {a b {{c d} e} {123 {{x}}}} {
+               set a [concat $a $i]
+       }
+  set a
+} {a b {c d} e 123 {{x}}}
+test foreach-1.3 {basic foreach tests} {catch {foreach} msg} 1
+test foreach-1.4 {basic foreach tests} {catch {foreach i} msg} 1
+test foreach-1.5 {basic foreach tests} {catch {foreach i j} msg} 1
+test foreach-1.6 {basic foreach tests} {catch {foreach i j k l} msg} 1
+test foreach-1.7 {basic foreach tests} {
+  set a {}
+  foreach i {} {
+               set a [concat $a $i]
+       }
+  set a
+} {}
+catch {unset a}
+test foreach-2.1 {foreach errors} {
+    list [catch {foreach {} {} {}} msg] $msg
+} {1 {foreach varlist is empty}}
+catch {unset a}
+
+test foreach-3.1 {parallel foreach tests} {
+  set x {}
+  foreach {a b} {1 2 3 4} {
+               append x $b $a
+       }
+  set x
+} {2143}
+test foreach-3.2 {parallel foreach tests} {
+  set x {}
+  foreach {a b} {1 2 3 4 5} {
+               append x $b $a
+  }
+       set x
+} {21435}
+test foreach-3.3 {parallel foreach tests} {
+  set x {}
+  foreach a {1 2 3} b {4 5 6} {
+               append x $b $a
+       }
+  set x
+} {415263}
+test foreach-3.4 {parallel foreach tests} {
+  set x {}
+  foreach a {1 2 3} b {4 5 6 7 8} {
+               append x $b $a
+       }
+  set x
+} {41526378}
+test foreach-3.5 {parallel foreach tests} {
+  set x {}
+  foreach {a b} {a b A B aa bb} c {c C cc CC} {
+               append x $a $b $c
+       }
+  set x
+} {abcABCaabbccCC}
+test foreach-3.6 {parallel foreach tests} {
+  set x {}
+  foreach a {1 2 3} b {1 2 3} c {1 2 3} d {1 2 3} e {1 2 3} {
+               append x $a $b $c $d $e
+  }
+       set x
+} {111112222233333}
+test foreach-3.7 {parallel foreach tests} {
+  set x {}
+  foreach a {} b {1 2 3} c {1 2} d {1 2 3 4} e {{1 2}} {
+               append x $a $b $c $d $e
+  }
+       set x
+} {1111 2222334}
+test foreach-4.1 {foreach only sets vars if repeating loop} {
+  proc foo {} {
+               set rgb {65535 0 0}
+               foreach {r g b} [set rgb] {}
+               return "r=$r, g=$g, b=$b"
+       }
+       foo
+} {r=65535, g=0, b=0}
+test foreach-5.1 {foreach supports dict syntactic sugar} {
+       proc foo {} {
+    set x {}
+    foreach {a(3)} {1 2 3 4} {lappend x [set {a(3)}]}
+               list $a $x
+       }
+       foo
+} {{3 4} {1 2 3 4}}
+
+test foreach-6.1 {noncompiled foreach and shared variable or value list objects that are converted to another type} {
+  catch {unset x}
+  foreach {12.0} {a b c} {
+    set x 12.0  
+    set x [expr $x + 1]
+  }
+  set x
+} 13.0
+
+# Check "continue".
+
+test foreach-7.1 {continue tests} {catch continue} 4
+test foreach-7.2 {continue tests} {
+  set a {}
+  foreach i {a b c d} {
+               if {[string compare $i "b"] == 0} continue
+               set a [concat $a $i]
+       }
+   set a
+} {a c d}
+test foreach-7.3 {continue tests} {
+       set a {}
+  foreach i {a b c d} {
+               if {[string compare $i "b"] != 0} continue
+               set a [concat $a $i]
+       }
+  set a
+} {b}
+test foreach-7.4 {continue tests} {catch {continue foo} msg} 1
+test foreach-7.5 {continue tests} {
+       catch {continue foo} msg
+  set msg
+} {wrong # args: should be "continue"}
+
+# Check "break".
+
+test foreach-8.1 {break tests} {catch break} 3
+test foreach-8.2 {break tests} {
+  set a {}
+       foreach i {a b c d} {
+               if {[string compare $i "c"] == 0} break
+               set a [concat $a $i]
+       }
+  set a
+} {a b}
+test foreach-8.3 {break tests} {catch {break foo} msg} 1
+test foreach-8.4 {break tests} {
+  catch {break foo} msg
+  set msg
+} {wrong # args: should be "break"}
+
+# Test for incorrect "double evaluation" semantics
+
+test foreach-9.1 {delayed substitution of body - knownbugs} {
+  proc foo {} {
+    set a 0
+    foreach a [list 1 2 3] "
+      set x $a
+    "
+    set x
+  }
+  foo
+} {0}
+
+# cleanup
+catch {unset a}
+catch {unset x}
+
+################################################################################
+# STRING
+################################################################################
+
+# string last
+test string-7.1 {string last, too few args} {
+    list [catch {string last a} msg] $msg
+} {1 {wrong # args: should be "string last subString string ?index?"}}
+test string-7.2 {string last, bad args} {
+    list [catch {string last a b c} msg] $msg
+} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
+test string-7.3 {string last, too many args} {
+    list [catch {string last a b c d} msg] $msg
+} {1 {wrong # args: should be "string last subString string ?index?"}}
+test string-7.5 {string last} {
+    string last xx xxxx123xx345x678
+} 7
+test string-7.13 {string last, start index} {
+    ## Constrain to last 'a' should work
+    string last ba badbad end-1
+} 3
+test string-7.14 {string last, start index} {
+    ## Constrain to last 'b' should skip last 'ba'
+    string last ba badbad end-2
+} 0
+
+## string match
+##
+test string-11.1 {string match, too few args} {
+    proc foo {} {string match a}
+    list [catch {foo} msg] $msg
+} {1 {wrong # args: should be "string match ?-nocase? pattern string"}}
+test string-11.2 {string match, too many args} {
+    proc foo {} {string match a b c d}
+    list [catch {foo} msg] $msg
+} {1 {wrong # args: should be "string match ?-nocase? pattern string"}}
+test string-11.3 {string match} {
+    proc foo {} {string match abc abc}
+    foo
+} 1
+#test string-11.4 {string match} {
+#    proc foo {} {string mat abc abd}
+#    foo
+#} 0
+test string-11.5 {string match} {
+    proc foo {} {string match ab*c abc}
+    foo
+} 1
+test string-11.6 {string match} {
+    proc foo {} {string match ab**c abc}
+    foo
+} 1
+test string-11.7 {string match} {
+    proc foo {} {string match ab* abcdef}
+    foo
+} 1
+test string-11.8 {string match} {
+    proc foo {} {string match *c abc}
+    foo
+} 1
+test string-11.9 {string match} {
+    proc foo {} {string match *3*6*9 0123456789}
+    foo
+} 1
+test string-11.10 {string match} {
+    proc foo {} {string match *3*6*9 01234567890}
+    foo
+} 0
+test string-11.11 {string match} {
+    proc foo {} {string match a?c abc}
+    foo
+} 1
+test string-11.12 {string match} {
+    proc foo {} {string match a??c abc}
+    foo
+} 0
+test string-11.13 {string match} {
+    proc foo {} {string match ?1??4???8? 0123456789}
+    foo
+} 1
+test string-11.14 {string match} {
+    proc foo {} {string match {[abc]bc} abc}
+    foo
+} 1
+test string-11.15 {string match} {
+    proc foo {} {string match {a[abc]c} abc}
+    foo
+} 1
+test string-11.16 {string match} {
+    proc foo {} {string match {a[xyz]c} abc}
+    foo
+} 0
+test string-11.17 {string match} {
+    proc foo {} {string match {12[2-7]45} 12345}
+    foo
+} 1
+test string-11.18 {string match} {
+    proc foo {} {string match {12[ab2-4cd]45} 12345}
+    foo
+} 1
+test string-11.19 {string match} {
+    proc foo {} {string match {12[ab2-4cd]45} 12b45}
+    foo
+} 1
+test string-11.20 {string match} {
+    proc foo {} {string match {12[ab2-4cd]45} 12d45}
+    foo
+} 1
+test string-11.21 {string match} {
+    proc foo {} {string match {12[ab2-4cd]45} 12145}
+    foo
+} 0
+test string-11.22 {string match} {
+    proc foo {} {string match {12[ab2-4cd]45} 12545}
+    foo
+} 0
+test string-11.23 {string match} {
+    proc foo {} {string match {a\*b} a*b}
+    foo
+} 1
+test string-11.24 {string match} {
+    proc foo {} {string match {a\*b} ab}
+    foo
+} 0
+test string-11.25 {string match} {
+    proc foo {} {string match {a\*\?\[\]\\\x} "a*?\[\]\\x"}
+    foo
+} 1
+test string-11.26 {string match} {
+    proc foo {} {string match ** ""}
+    foo
+} 1
+test string-11.27 {string match} {
+    proc foo {} {string match *. ""}
+    foo
+} 0
+test string-11.28 {string match} {
+    proc foo {} {string match "" ""}
+    foo
+} 1
+test string-11.29 {string match} {
+    proc foo {} {string match \[a a}
+    foo
+} 1
+test string-11.31 {string match case} {
+    proc foo {} {string match a A}
+    foo
+} 0
+test string-11.32 {string match nocase} {
+    proc foo {} {string match -n a A}
+    foo
+} 1
+#test string-11.33 {string match nocase} {
+#    proc foo {} {string match -nocase a\334 A\374}
+#    foo
+#} 1
+test string-11.34 {string match nocase} {
+    proc foo {} {string match -nocase a*f ABCDEf}
+    foo
+} 1
+test string-11.35 {string match case, false hope} {
+    # This is true because '_' lies between the A-Z and a-z ranges
+    proc foo {} {string match {[A-z]} _}
+    foo
+} 1
+test string-11.36 {string match nocase range} {
+    # This is false because although '_' lies between the A-Z and a-z ranges,
+    # we lower case the end points before checking the ranges.
+    proc foo {} {string match -nocase {[A-z]} _}
+    foo
+} 0
+test string-11.37 {string match nocase} {
+    proc foo {} {string match -nocase {[A-fh-Z]} g}
+    foo
+} 0
+test string-11.38 {string match case, reverse range} {
+    proc foo {} {string match {[A-fh-Z]} g}
+    foo
+} 1
+test string-11.39 {string match, *\ case} {
+    proc foo {} {string match {*\abc} abc}
+    foo
+} 1
+test string-11.40 {string match, *special case} {
+    proc foo {} {string match {*[ab]} abc}
+    foo
+} 0
+test string-11.41 {string match, *special case} {
+    proc foo {} {string match {*[ab]*} abc}
+    foo
+} 1
+#test string-11.42 {string match, *special case} {
+#    proc foo {} {string match "*\\" "\\"}
+#    foo
+#} 0
+test string-11.43 {string match, *special case} {
+    proc foo {} {string match "*\\\\" "\\"}
+    foo
+} 1
+test string-11.44 {string match, *special case} {
+    proc foo {} {string match "*???" "12345"}
+    foo
+} 1
+test string-11.45 {string match, *special case} {
+    proc foo {} {string match "*???" "12"}
+    foo
+} 0
+test string-11.46 {string match, *special case} {
+    proc foo {} {string match "*\\*" "abc*"}
+    foo
+} 1
+test string-11.47 {string match, *special case} {
+    proc foo {} {string match "*\\*" "*"}
+    foo
+} 1
+test string-11.48 {string match, *special case} {
+    proc foo {} {string match "*\\*" "*abc"}
+    foo
+} 0
+test string-11.49 {string match, *special case} {
+    proc foo {} {string match "?\\*" "a*"}
+    foo
+} 1
+#test string-11.50 {string match, *special case} {
+#    proc foo {} {string match "\\" "\\"}
+#    foo
+#} 0
+
+## string length
+##
+test string-9.1 {string length} {
+    proc foo {} {string length}
+    list [catch {foo} msg] $msg
+} {1 {wrong # args: should be "string length string"}}
+test string-9.2 {string length} {
+    proc foo {} {string length a b}
+    list [catch {foo} msg] $msg
+} {1 {wrong # args: should be "string length string"}}
+test string-9.3 {string length} {
+    proc foo {} {string length "a little string"}
+    foo
+} 15
+
+# string map
+
+test string-10.4 {string map} {
+    string map {a b} abba
+} {bbbb}
+test string-10.5 {string map} {
+    string map {a b} a
+} {b}
+test string-10.6 {string map -nocase} {
+    string map -nocase {a b} Abba
+} {bbbb}
+test string-10.7 {string map} {
+    string map {abc 321 ab * a A} aabcabaababcab
+} {A321*A*321*}
+test string-10.8 {string map -nocase} {
+    string map -nocase {aBc 321 Ab * a A} aabcabaababcab
+} {A321*A*321*}
+test string-10.10 {string map} {
+    list [catch {string map {a b c} abba} msg] $msg
+} {1 {list must contain an even number of elements}}
+test string-10.11 {string map, nulls} {
+    string map {\x00 NULL blah \x00nix} {qwerty}
+} {qwerty}
+test string-10.12 {string map, unicode} {
+    string map [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU"
+} aueue\u00dc\0EU
+test string-10.13 {string map, -nocase unicode} {
+    string map -nocase [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU"
+} aue\u00dc\u00dc\0EU
+test string-10.14 {string map, -nocase null arguments} {
+    string map -nocase {{} abc} foo
+} foo
+test string-10.15 {string map, one pair case} {
+    string map -nocase {abc 32} aAbCaBaAbAbcAb
+} {a32aBaAb32Ab}
+test string-10.16 {string map, one pair case} {
+    string map -nocase {ab 4321} aAbCaBaAbAbcAb
+} {a4321C4321a43214321c4321}
+test string-10.17 {string map, one pair case} {
+    string map {Ab 4321} aAbCaBaAbAbcAb
+} {a4321CaBa43214321c4321}
+test string-10.18 {string map, empty argument} {
+    string map -nocase {{} abc} foo
+} foo
+test string-10.19 {string map, empty arguments} {
+    string map -nocase {{} abc f bar {} def} foo
+} baroo
+
+################################################################################
+# SPLIT
+################################################################################
+
+test split-1.1 {basic split commands} {
+    split "a\n b\t\r c\n "
+} {a {} b {} {} c {} {}}
+test split-1.2 {basic split commands} {
+    split "word 1xyzword 2zword 3" xyz
+} {{word 1} {} {} {word 2} {word 3}}
+test split-1.3 {basic split commands} {
+    split "12345" {}
+} {1 2 3 4 5}
+test split-1.4 {basic split commands} {
+    split "a\}b\[c\{\]\$"
+} "a\\}b\\\[c\\{\\\]\\\$"
+test split-1.5 {basic split commands} {
+    split {} {}
+} {}
+test split-1.6 {basic split commands} {
+    split {}
+} {}
+test split-1.7 {basic split commands} {
+    split {   }
+} {{} {} {} {}}
+test split-1.8 {basic split commands} {
+    proc foo {} {
+        set x {}
+        foreach f [split {]\n} {}] {
+            append x $f
+        }
+        return $x      
+    }
+    foo
+} {]\n}
+test split-1.9 {basic split commands} {
+    proc foo {} {
+        set x ab\000c
+        set y [split $x {}]
+        return $y
+    }
+    foo
+} "a b \000 c"
+test split-1.10 {basic split commands} {
+    split "a0ab1b2bbb3\000c4" ab\000c
+} {{} 0 {} 1 2 {} {} 3 {} 4}
+test split-1.11 {basic split commands} {
+    split "12,3,45" {,}
+} {12 3 45}
+test split-1.12 {basic split commands} {
+    split "\u0001ab\u0001cd\u0001\u0001ef\u0001" \1
+} {{} ab cd {} ef {}}
+test split-1.13 {basic split commands} {
+    split "12,34,56," {,}
+} {12 34 56 {}}
+test split-1.14 {basic split commands} {
+    split ",12,,,34,56," {,}
+} {{} 12 {} {} 34 56 {}}
+
+test split-2.1 {split errors} {
+    list [catch split msg] $msg
+} {1 {wrong # args: should be "split string ?splitChars?"}}
+test split-2.2 {split errors} {
+    list [catch {split a b c} msg] $msg
+} {1 {wrong # args: should be "split string ?splitChars?"}}
+
+# cleanup
+catch {rename foo {}}
+
+################################################################################
+# JOIN
+################################################################################
+
+test join-1.1 {basic join commands} {
+    join {a b c} xyz
+} axyzbxyzc
+test join-1.2 {basic join commands} {
+    join {a b c} {}
+} abc
+test join-1.3 {basic join commands} {
+    join {} xyz
+} {}
+test join-1.4 {basic join commands} {
+    join {12 34 56}
+} {12 34 56}
+
+test join-2.1 {join errors} {
+    list [catch join msg] $msg
+} {1 {wrong # args: should be "join list ?joinString?"}}
+test join-2.2 {join errors} {
+    list [catch {join a b c} msg] $msg
+} {1 {wrong # args: should be "join list ?joinString?"}}
+#test join-2.3 {join errors} {
+#    list [catch {join "a \{ c" 111} msg] $msg
+#} {1 {unmatched open brace in list}}
+
+test join-3.1 {joinString is binary ok} {
+  string length [join {a b c} a\0b]
+} 9
+
+test join-3.2 {join is binary ok} {
+  string length [join "a\0b a\0b a\0b"]
+} 11
+
+################################################################################
+# SWITCH
+################################################################################
+
+test switch-1.1 {simple patterns} {
+    switch a a {expr 1} b {expr 2} c {expr 3} default {expr 4}
+} 1
+test switch-1.2 {simple patterns} {
+    switch b a {expr 1} b {expr 2} c {expr 3} default {expr 4}
+} 2
+test switch-1.3 {simple patterns} {
+    switch x a {expr 1} b {expr 2} c {expr 3} default {expr 4}
+} 4
+test switch-1.4 {simple patterns} {
+    switch x a {expr 1} b {expr 2} c {expr 3}
+} {}
+test switch-1.5 {simple pattern matches many times} {
+    switch b a {expr 1} b {expr 2} b {expr 3} b {expr 4}
+} 2
+test switch-1.6 {simple patterns} {
+    switch default a {expr 1} default {expr 2} c {expr 3} default {expr 4}
+} 2
+test switch-1.7 {simple patterns} {
+    switch x a {expr 1} default {expr 2} c {expr 3} default {expr 4}
+} 4
+
+test switch-2.1 {single-argument form for pattern/command pairs} {
+    switch b {
+       a {expr 1}
+       b {expr 2}
+       default {expr 6}
+    }
+} {2}
+test switch-2.2 {single-argument form for pattern/command pairs} {
+    list [catch {switch z {a 2 b}}]
+} 1
+
+test switch-3.1 {-exact vs. -glob vs. -regexp} {
+    switch -exact aaaab {
+       ^a*b$   {concat regexp}
+       *b      {concat glob}
+       aaaab   {concat exact}
+       default {concat none}
+    }
+} exact
+test switch-3.2 {-exact vs. -glob vs. -regexp (no [regexp] cmd)} regexp {
+       rename regexp regexp.none
+    set rc [catch {
+        switch -regexp aaaab {
+        ^a*b$  {concat regexp}
+        *b     {concat glob}
+        aaaab  {concat exact}
+        default        {concat none}
+        }
+    }]
+       rename regexp.none regexp
+       set rc
+} 1
+
+test switch-3.3 {-exact vs. -glob vs. -regexp (with [regexp] cmd)} regexp {
+    switch -regexp aaaab {
+       ^a*b$   {concat regexp}
+       *b          {concat glob}
+       aaaab   {concat exact}
+       default {concat none}
+    }
+} regexp
+test switch-3.4 {-exact vs. -glob vs. -regexp} {
+    switch -glob aaaab {
+       ^a*b$   {concat regexp}
+       *b          {concat glob}
+       aaaab   {concat exact}
+       default {concat none}
+    }
+} glob
+test switch-3.5 {-exact vs. -glob vs. -regexp} {
+    switch aaaab {^a*b$} {concat regexp} *b {concat glob} \
+           aaaab {concat exact} default {concat none}
+} exact
+test switch-3.6 {-exact vs. -glob vs. -regexp} {
+    switch -- -glob {
+       ^g.*b$  {concat regexp}
+       -*      {concat glob}
+       -glob   {concat exact}
+       default {concat none}
+    }
+} exact
+test switch-3.7 {-exact vs. -glob vs. -regexp} {
+    list [catch {switch -foo a b c} msg] $msg
+} {1 {bad option "-foo": must be -exact, -glob, -regexp, -command procname or --}}
+
+test switch-4.1 {error in executed command} {
+    list [catch {switch a a {error "Just a test"} default {expr 1}} msg] \
+           $msg
+} {1 {Just a test}}
+test switch-4.2 {error: not enough args} {
+    catch {switch}
+} 1
+test switch-4.3 {error: pattern with no body} {
+    catch {switch a b}
+} 1
+test switch-4.4 {error: pattern with no body} {
+    catch {switch a b {expr 1} c}
+} 1
+test switch-4.5 {error in default command} {
+    list [catch {switch foo a {error switch1} b {error switch 3} \
+           default {error switch2}} msg] $msg
+} {1 switch2}
+
+test switch-5.1 {errors in -regexp matching} regexp {
+    catch {switch -regexp aaaab {
+       *b      {concat glob}
+       aaaab   {concat exact}
+       default {concat none}
+    }} msg
+} 1
+
+test switch-6.1 {backslashes in patterns} {
+    switch -exact {\a\$\.\[} {
+       \a\$\.\[        {concat first}
+       \a\\$\.\\[      {concat second}
+       \\a\\$\\.\\[    {concat third}
+       {\a\\$\.\\[}    {concat fourth}
+       {\\a\\$\\.\\[}  {concat fifth}
+       default         {concat none}
+    }
+} third
+test switch-6.2 {backslashes in patterns} {
+    switch -exact {\a\$\.\[} {
+       \a\$\.\[        {concat first}
+       {\a\$\.\[}      {concat second}
+       {{\a\$\.\[}}    {concat third}
+       default         {concat none}
+    }
+} second
+
+test switch-7.1 {"-" bodies} {
+    switch a {
+       a -
+       b -
+       c {concat 1}
+       default {concat 2}
+    }
+} 1
+test switch-7.2 {"-" bodies} {
+    list [catch {
+       switch a {
+           a -
+           b -
+           c -
+       }
+    } msg] $msg
+} {1 {no body specified for pattern "c"}}
+# Following original Tcl test makes no sense, I feel! Please review ...
+#~ test switch-7.3 {"-" bodies} {
+    #~ list [catch {
+       #~ switch a {
+           #~ a -
+           #~ b -foo
+           #~ c -
+       #~ }
+    #~ } msg] $msg
+#~ } {1 {no body specified for pattern "c"}}
+test switch-7.3 {"-" bodies} {
+    list [catch {
+       switch a {
+           a -
+           b -foo
+           c -
+       }
+    } msg] $msg
+} {1 {invalid command name "-foo"}}
+
+test switch-8.1 {empty body} {
+    set msg {}
+    switch {2} {
+       1 {set msg 1}
+        2 {}
+        default {set msg 2}
+    }
+} {}
+
+test switch-9.1 {empty pattern/body list} {
+    catch {switch x}
+} 1
+test switch-9.2 {empty pattern/body list} {
+    catch {switch -- x} 
+} 1 
+test switch-9.3 {empty pattern/body list} {
+    catch {switch x {}} 
+} 1
+test switch-9.4 {empty pattern/body list} {
+    catch {switch -- x {}}
+} 1
+test switch-9.5 {unpaired pattern} {
+    catch {switch x a {} b}
+} 1
+test switch-9.6 {unpaired pattern} {
+    catch {switch x {a {} b}}
+} 1
+test switch-9.7 {unpaired pattern} {
+    catch {switch x a {} # comment b}
+} 1
+test switch-9.8 {unpaired pattern} {
+    catch {switch x {a {} # comment b}}
+} 1
+test switch-9.9 {unpaired pattern} {
+    catch {switch x a {} x {} # comment b}
+} 1
+test switch-9.10 {unpaired pattern} {
+    catch {switch x {a {} x {} # comment b}}
+} 1
+
+test switch-10.1 {no callback given to -command} {
+    catch {switch -command a { a {expr 1} b {expr 2} }} 
+} 1
+test switch-10.2 {callback expect wrong # args for -command} lambda {
+    catch {switch -command [lambda {p1} {expr 1}] a { a {expr 1} b {expr 2} }}
+} 1
+test switch-10.3 {callback to -command returns ever 0: no match} lambda {
+    switch -command [lambda {p1 p2} {expr 0}] a a {expr 1} b {expr 2}
+} {}
+test switch-10.4 {callback to -command returns 3 at first match} lambda {
+    switch -command [lambda {p1 p2} {expr 3}] a a {expr 1} b {expr 2}
+} 1
+test switch-10.5 {[error] in callback to -command} lambda {
+    list [catch {
+        switch -command [lambda {p1 p2} {error "foo"}] a a {expr 1} b {expr 2}
+    } msg] $msg
+} {1 foo}
+test switch-10.6 {[continue] in callback to -command} lambda {
+    list [catch {
+        switch -command [lambda {p1 p2} {continue}] a a {expr 1} b {expr 2}
+    } msg] $msg
+} {4 {}}
+test switch-10.7 {callback matches first if pat < str} lambda {
+    switch -command [lambda {pat str} {expr {$pat < $str}}] 3 \
+        5 {expr 1} 3 {expr 2}
+} {}
+test switch-10.8 {callback matches first if pat < str} lambda {
+    switch -command [lambda {pat str} {expr {$pat < $str}}] 7 \
+        5 {expr 1} 3 {expr 2}
+} 1
+test switch-10.9 {callback matches first if pat < str} lambda {
+    switch -command [lambda {pat str} {expr {$pat < $str}}] 4 \
+        5 {expr 1} 3 {expr 2}
+} 2
+
+################################################################################
+# FOR
+################################################################################
+
+# Basic "for" operation.
+test for-1.1 {TclCompileForCmd: missing initial command} {
+    list [catch {for} msg] $msg
+} {1 {wrong # args: should be "for start test next body"}}
+test for-1.2 {TclCompileForCmd: error in initial command} {
+    list [catch {for {set}} msg] $msg
+} {1 {wrong # args: should be "for start test next body"}}
+catch {unset i}
+test for-1.3 {TclCompileForCmd: missing test expression} {
+    catch {for {set i 0}} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+test for-1.5 {TclCompileForCmd: test expression is enclosed in quotes} {
+    set i 0
+    for {} "$i > 5" {incr i} {}
+} {}
+test for-1.6 {TclCompileForCmd: missing "next" command} {
+    catch {for {set i 0} {$i < 5}} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+test for-1.7 {TclCompileForCmd: missing command body} {
+    catch {for {set i 0} {$i < 5} {incr i}} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+catch {unset a}
+test for-1.9 {TclCompileForCmd: simple command body} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==4 break
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3}
+test for-1.10 {TclCompileForCmd: command body in quotes} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} "append a x"
+    set a
+} {xxxxx}
+test for-1.11 {TclCompileForCmd: computed command body} {
+    catch {unset x1}
+    catch {unset bb}
+    catch {unset x2}
+    set x1 {append a x1; }
+    set bb {break}
+    set x2 {; append a x2}
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2
+    set a
+} {x1}
+test for-1.13 {TclCompileForCmd: long command body} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==4 break
+       if $i>5 continue
+        set tcl_platform(machine) i686
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3}
+test for-1.14 {TclCompileForCmd: for command result} {
+    set a [for {set i 0} {$i < 5} {incr i} {}]
+    set a
+} {}
+test for-1.15 {TclCompileForCmd: for command result} {
+    set a [for {set i 0} {$i < 5} {incr i} {if $i==3 break}]
+    set a
+} {}
+
+# Check "for" and "continue".
+
+test for-2.1 {TclCompileContinueCmd: arguments after "continue"} {
+    catch {continue foo} msg
+    set msg
+} {wrong # args: should be "continue"}
+test for-2.2 {TclCompileContinueCmd: continue result} {
+    catch continue
+} 4
+test for-2.3 {continue tests} {
+    set a {}
+    for {set i 1} {$i <= 4} {set i [expr $i+1]} {
+       if {$i == 2} continue
+       set a [concat $a $i]
+    }
+    set a
+} {1 3 4}
+test for-2.4 {continue tests} {
+    set a {}
+    for {set i 1} {$i <= 4} {set i [expr $i+1]} {
+       if {$i != 2} continue
+       set a [concat $a $i]
+    }
+    set a
+} {2}
+test for-2.5 {continue tests, nested loops} {
+    set msg {}
+    for {set i 1} {$i <= 4} {incr i} {
+       for {set a 1} {$a <= 2} {incr a} {
+            if {$i>=2 && $a>=2} continue
+            set msg [concat $msg "$i.$a"]
+        }
+    }
+    set msg
+} {1.1 1.2 2.1 3.1 4.1}
+test for-2.6 {continue tests, long command body} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==2 continue
+       if $i==4 break
+       if $i>5 continue
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       set a [concat $a $i]
+    }
+    set a
+} {1 3}
+
+# Check "for" and "break".
+
+test for-3.1 {TclCompileBreakCmd: arguments after "break"} {
+    catch {break foo} msg
+    set msg
+} {wrong # args: should be "break"}
+test for-3.2 {TclCompileBreakCmd: break result} {
+    catch break
+} 3
+test for-3.3 {break tests} {
+    set a {}
+    for {set i 1} {$i <= 4} {incr i} {
+       if {$i == 3} break
+       set a [concat $a $i]
+    }
+    set a
+} {1 2}
+test for-3.4 {break tests, nested loops} {
+    set msg {}
+    for {set i 1} {$i <= 4} {incr i} {
+       for {set a 1} {$a <= 2} {incr a} {
+            if {$i>=2 && $a>=2} break
+            set msg [concat $msg "$i.$a"]
+        }
+    }
+    set msg
+} {1.1 1.2 2.1 3.1 4.1}
+test for-3.5 {break tests, long command body} {
+    set a {}
+    for {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==2 continue
+       if $i==5 break
+       if $i>5 continue
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i == 4} break
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       set a [concat $a $i]
+    }
+    set a
+} {1 3}
+test for-4.1 {break must reset the interp result} {
+    catch {
+        set z GLOBTESTDIR/dir2/file2.c
+        if [string match GLOBTESTDIR/dir2/* $z] {
+            break
+        }
+    } j
+    set j
+} {}
+
+# Test for incorrect "double evaluation" semantics
+
+test for-5.1 {possible delayed substitution of increment command} {
+    # Increment should be 5, and lappend should always append $a
+    catch {unset a}
+    catch {unset i}
+    set a 5
+    set i {}
+    for {set a 1} {$a < 12} "incr a $a" {lappend i $a}
+    set i
+} {1 6 11}
+
+test for-5.2 {possible delayed substitution of increment command} {
+    # Increment should be 5, and lappend should always append $a
+    catch {rename p ""}
+    proc p {} {
+       set a 5
+       set i {}
+       for {set a 1} {$a < 12} "incr a $a" {lappend i $a}
+       set i
+    }
+    p
+} {1 6 11}
+test for-5.3 {possible delayed substitution of body command} {
+    # Increment should be $a, and lappend should always append 5
+    set a 5
+    set i {}
+    for {set a 1} {$a < 12} {incr a $a} "lappend i $a"
+    set i
+} {5 5 5 5}
+test for-5.4 {possible delayed substitution of body command} {
+    # Increment should be $a, and lappend should always append 5
+    catch {rename p ""}
+    proc p {} {
+       set a 5
+       set i {}
+       for {set a 1} {$a < 12} {incr a $a} "lappend i $a"
+       set i
+    }
+    p
+} {5 5 5 5}
+
+# In the following tests we need to bypass the bytecode compiler by
+# substituting the command from a variable.  This ensures that command
+# procedure is invoked directly.
+
+test for-6.1 {Tcl_ForObjCmd: number of args} {
+    set z for
+    catch {$z} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+test for-6.2 {Tcl_ForObjCmd: number of args} {
+    set z for
+    catch {$z {set i 0}} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+test for-6.3 {Tcl_ForObjCmd: number of args} {
+    set z for
+    catch {$z {set i 0} {$i < 5}} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+test for-6.4 {Tcl_ForObjCmd: number of args} {
+    set z for
+    catch {$z {set i 0} {$i < 5} {incr i}} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+test for-6.5 {Tcl_ForObjCmd: number of args} {
+    set z for
+    catch {$z {set i 0} {$i < 5} {incr i} {body} extra} msg
+    set msg
+} {wrong # args: should be "for start test next body"}
+test for-6.6 {Tcl_ForObjCmd: error in initial command} {
+    set z for
+    list [catch {$z {set} {$i < 5} {incr i} {body}} msg] $msg
+} {1 {wrong # args: should be "set varName ?newValue?"}}
+test for-6.8 {Tcl_ForObjCmd: test expression is enclosed in quotes} {
+    set z for
+    set i 0
+    $z {set i 6} "$i > 5" {incr i} {set y $i}
+    set i
+} 6
+test for-6.10 {Tcl_ForObjCmd: simple command body} {
+    set z for
+    set a {}
+    $z {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==4 break
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3}
+test for-6.11 {Tcl_ForObjCmd: command body in quotes} {
+    set z for
+    set a {}
+    $z {set i 1} {$i<6} {set i [expr $i+1]} "append a x"
+    set a
+} {xxxxx}
+test for-6.12 {Tcl_ForObjCmd: computed command body} {
+    set z for
+    catch {unset x1}
+    catch {unset bb}
+    catch {unset x2}
+    set x1 {append a x1; }
+    set bb {break}
+    set x2 {; append a x2}
+    set a {}
+    $z {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2
+    set a
+} {x1}
+test for-6.14 {Tcl_ForObjCmd: long command body} {
+    set z for
+    set a {}
+    $z {set i 1} {$i<6} {set i [expr $i+1]} {
+       if $i==4 break
+       if $i>5 continue
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       if {$i>6 && $tcl_platform(machine) eq "xxx"} {
+           catch {set a $a} msg
+           catch {incr i 5} msg
+           catch {incr i -5} msg
+       }
+       set a [concat $a $i]
+    }
+    set a
+} {1 2 3}
+test for-6.15 {Tcl_ForObjCmd: for command result} {
+    set z for
+    set a [$z {set i 0} {$i < 5} {incr i} {}]
+    set a
+} {}
+test for-6.16 {Tcl_ForObjCmd: for command result} {
+    set z for
+    set a [$z {set i 0} {$i < 5} {incr i} {if $i==3 break}]
+    set a
+} {}
+
+
+################################################################################
+# INFO
+################################################################################
+
+test info-1.1 {info body option} {
+    proc t1 {} {body of t1}
+    info body t1
+} {body of t1}
+test info-1.2 {info body option} {
+    list [catch {info body set} msg] $msg
+} {1 {command "set" is not a procedure}}
+test info-1.3 {info body option} {
+    list [catch {info args set 1} msg] $msg
+} {1 {wrong # args: should be "info args procname"}}
+test info-1.5 {info body option, returning bytecompiled bodies} {
+    catch {unset args}
+    proc foo {args} {
+        foreach v $args {
+            upvar $v var
+            return "variable $v existence: [info exists var]"
+        }
+    }
+    foo a
+    list [catch [info body foo] msg] $msg
+} {1 {can't read "args": no such variable}}
+test info-1.6 {info body option, returning list bodies} {
+    proc foo args [list subst bar]
+    list [string length [info body foo]] \
+           [foo; string length [info body foo]]
+} {9 9}
+test info-2.1 {info commands option} {
+    proc t1 {} {}
+    proc t2 {} {}
+    set x " [info commands] "
+    list [string match {* t1 *} $x] [string match {* t2 *} $x] \
+            [string match {* set *} $x] [string match {* list *} $x]
+} {1 1 1 1}
+test info-2.2 {info commands option} {
+    proc t1 {} {}
+    rename t1 {}
+    set x [info commands]
+    string match {* t1 *} $x
+} 0
+test info-2.3 {info commands option} {
+    proc _test1_ {} {}
+    proc _test2_ {} {}
+    info commands _test1_
+} _test1_
+test info-2.4 {info commands option} {
+    proc _test1_ {} {}
+    proc _test2_ {} {}
+    lsort [info commands _test*]
+} {_test1_ _test2_}
+catch {rename _test1_ {}}
+catch {rename _test2_ {}}
+test info-2.5 {info commands option} {
+    list [catch {info commands a b} msg] $msg
+} {1 {wrong # args: should be "info commands ?pattern?"}}
+test info-3.1 {info exists option} {
+    set value foo
+    info exists value
+} 1
+catch {unset _nonexistent_}
+test info-3.2 {info exists option} {
+    info exists _nonexistent_
+} 0
+test info-3.3 {info exists option} {
+    proc t1 {x} {return [info exists x]}
+    t1 2
+} 1
+test info-3.4 {info exists option} {
+    proc t1 {x} {
+        global _nonexistent_
+        return [info exists _nonexistent_]
+    }
+    t1 2
+} 0
+test info-3.5 {info exists option} {
+    proc t1 {x} {
+        set y 47
+        return [info exists y]
+    }
+    t1 2
+} 1
+test info-3.6 {info exists option} {
+    proc t1 {x} {return [info exists value]}
+    t1 2
+} 0
+test info-3.7 {info exists option} {
+    catch {unset x}
+    set x(2) 44
+    list [info exists x] [info exists x(1)] [info exists x(2)]
+} {1 0 1}
+catch {unset x}
+test info-3.8 {info exists option} {
+    list [catch {info exists} msg] $msg
+} {1 {wrong # args: should be "info exists varName"}}
+test info-3.9 {info exists option} {
+    list [catch {info exists 1 2} msg] $msg
+} {1 {wrong # args: should be "info exists varName"}}
+test info-4.1 {info globals option} {
+    set x 1
+    set y 2
+    set value 23
+    set a " [info globals] "
+    list [string match {* x *} $a] [string match {* y *} $a] \
+            [string match {* value *} $a] [string match {* _foobar_ *} $a]
+} {1 1 1 0}
+test info-4.2 {info globals option} {
+    set _xxx1 1
+    set _xxx2 2
+    lsort [info globals _xxx*]
+} {_xxx1 _xxx2}
+test info-4.3 {info globals option} {
+    list [catch {info globals 1 2} msg] $msg
+} {1 {wrong # args: should be "info globals ?pattern?"}}
+test info-5.1 {info level option} {
+    info level
+} 0
+
+test info-5.2 {info level option} {
+    proc t1 {a b} {
+        set x [info level]
+        set y [info level 1]
+        list $x $y
+    }
+    t1 146 testString
+} {1 {t1 146 testString}}
+test info-5.3 {info level option} {
+    proc t1 {a b} {
+        t2 [expr $a*2] $b
+    }
+    proc t2 {x y} {
+        list [info level] [info level 1] [info level 2] [info level -1] \
+                [info level 0]
+    }
+    t1 146 {a {b c} {{{c}}}}
+} {2 {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}} {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}}}
+test info-5.4 {info level option} {
+    proc t1 {} {
+        set x [info level]
+        set y [info level 1]
+        list $x $y
+    }
+    t1
+} {1 t1}
+test info-5.5 {info level option} {
+    list [catch {info level 1 2} msg] $msg
+} {1 {wrong # args: should be "info level ?levelNum?"}}
+test info-5.6 {info level option} {
+    list [catch {info level 123a} msg] $msg
+} {1 {bad level "123a"}}
+test info-5.7 {info level option} {
+    list [catch {info level 0} msg] $msg
+} {1 {bad level "0"}}
+test info-5.8 {info level option} {
+    proc t1 {} {info level -1}
+    list [catch {t1} msg] $msg
+} {1 {bad level "-1"}}
+test info-5.9 {info level option} {
+    proc t1 {x} {info level $x}
+    list [catch {t1 -3} msg] $msg
+} {1 {bad level "-3"}}
+test info-6.1 {info locals option} {
+    set a 22
+    proc t1 {x y} {
+        set b 13
+        set c testing
+        global a
+       global aa
+       set aa 23
+        return [info locals]
+    }
+    lsort [t1 23 24]
+} {b c x y}
+test info-6.2 {info locals option} {
+    proc t1 {x y} {
+        set xx1 2
+        set xx2 3
+        set y 4
+        return [info locals x*]
+    }
+    lsort [t1 2 3]
+} {x xx1 xx2}
+test info-6.3 {info locals option} {
+    list [catch {info locals 1 2} msg] $msg
+} {1 {wrong # args: should be "info locals ?pattern?"}}
+test info-6.4 {info locals option} {
+    info locals
+} {}
+test info-6.5 {info locals option} {
+    proc t1 {} {return [info locals]}
+    t1
+} {}
+test info-6.6 {info locals vs unset compiled locals} {
+    proc t1 {lst} {
+        foreach $lst $lst {}
+        unset lst
+        return [info locals]
+    }
+    lsort [t1 {a b c c d e f}]
+} {a b c d e f}
+test info-6.7 {info locals with temporary variables} {
+    proc t1 {} {
+        foreach a {b c} {}
+        info locals
+    }
+    t1
+} {a}
+test info-7.1 {info vars option} {
+    set a 1
+    set b 2
+    proc t1 {x y} {
+        global a b
+        set c 33
+        return [info vars]
+    }
+    lsort [t1 18 19]
+} {a b c x y}
+test info-7.2 {info vars option} {
+    set xxx1 1
+    set xxx2 2
+    proc t1 {xxa y} {
+        global xxx1 xxx2
+        set c 33
+        return [info vars x*]
+    }
+    lsort [t1 18 19]
+} {xxa xxx1 xxx2}
+test info-7.3 {info vars option} {
+    lsort [info vars]
+} [lsort [info globals]]
+test info-7.4 {info vars option} {
+    list [catch {info vars a b} msg] $msg
+} {1 {wrong # args: should be "info vars ?pattern?"}}
+test info-7.5 {info vars with temporary variables} {
+    proc t1 {} {
+        foreach a {b c} {}
+        info vars
+    }
+    t1
+} {a}
+
+################################################################################
+# RANGE
+################################################################################
+
+test range-1.1 {basic range tests} {
+    range 0 10
+} {0 1 2 3 4 5 6 7 8 9}
+
+test range-1.2 {basic range tests} {
+    range 10 0 -1
+} {10 9 8 7 6 5 4 3 2 1}
+
+test range-1.3 {basic range tests} {
+    range 1 10 11
+} {1}
+
+test range-1.4 {basic range tests} {
+    range 1 10 11
+} {1}
+
+test range-1.5 {basic range tests} {
+    range 10 10
+} {}
+
+test range-1.6 {basic range tests} {
+    range 10 10 2
+} {}
+
+test range-1.7 {basic range test} {
+    range 5
+} {0 1 2 3 4}
+
+test range-1.8 {basic range test} {
+    range -10 -20 -2
+} {-10 -12 -14 -16 -18}
+
+test range-1.9 {basic range test} {
+    range -20 -10 3
+} {-20 -17 -14 -11}
+
+test range-2.0 {foreach range test} {
+    set k 0
+    foreach {x y} [range 100] {
+       incr k [expr {$x*$y}]
+    }
+    set k
+} {164150}
+
+test range-2.1 {foreach range test without obj reuse} {
+    set k 0
+    set trash {}
+    foreach {x y} [range 100] {
+       incr k [expr {$x*$y}]
+       lappend trash $x $y
+    }
+    set trash {}
+    set k
+} {164150}
+
+test range-2.2 {range element shimmering test} {
+    set k {}
+    foreach x [range 0 10] {
+       append k [llength $x]
+    }
+    set k
+} {1111111111}
+
+test range-3.0 {llength range test} {
+    llength [range 5000]
+} {5000}
+
+test range-3.1 {llength range test} {
+    llength [range 5000 5000]
+} {0}
+
+test range-4.0 {lindex range test} {
+    lindex [range 1000] 500
+} {500}
+
+test range-4.1 {lindex range test} {
+    lindex [range 1000] end-2
+} {997}
+
+test range-5.0 {lindex llength range test} {
+    set k 0
+    set trash {}
+    set r [range 100]
+    for {set i 0} {$i < [llength $r]} {incr i 2} {
+       incr k [expr {[lindex $r $i]*[lindex $r [expr {$i+1}]]}]
+    }
+    set trash {}
+    set k
+} {164150}
+
+################################################################################
+# SCOPE
+################################################################################
+if 0 {
+test scope-1.0 {Non existing var} {
+    catch {unset x}
+    scope x {
+        set x 10
+        set y [+ $x 1]
+    }
+    list [info exists x] $y
+} {0 11}
+
+test scope-1.1 {Existing var restore} {
+    set x 100
+    scope x {
+        for {set x 0} {$x < 10} {incr x} {}
+    }
+    set x
+} {100}
+
+test scope-1.2 {Mix of 1.0 and 1.1 tests} {
+    catch {unset x}
+    set y 10
+    scope {x y} {
+        set y 100
+        set x 200
+    }
+    list [info exists x] $y
+} {0 10}
+
+test scope-1.3 {Array element} {
+    set x "a 1 b 2"
+    scope x(a) {
+        set x(a) Hello!
+    }
+    set x(a)
+} {1}
+
+test scope-1.4 {Non existing array element} {
+    catch {unset x}
+    scope x(a) {
+        set x(a) Hello!
+    }
+    info exists x(a)
+} {0}
+
+test scope-1.5 {Info exists} {
+    set x foo
+    scope x {
+        info exists x
+    }
+} {0}
+
+catch {unset x}
+catch {unset y}
+}
+
+################################################################################
+# RAND
+################################################################################
+test rand-1.0 {Only one output is valid} {
+    list [rand 100 100] [rand 101 101]
+} {100 101}
+
+test rand-1.1 {invalid arguments} {
+    catch {rand 100 50} err
+    set err
+} {Invalid arguments (max < min)}
+
+test rand-1.2 {Check limits} {
+    set sum 0
+    for {set i 0} {$i < 100} {incr i} {
+        incr sum [expr {([rand $i] >= 0)+([rand $i] < 100)}]
+    }
+    set sum
+} {200}
+
+catch {unset sum; unset err; unset i}
+
+################################################################################
+# JIM REGRESSION TESTS
+################################################################################
+test regression-1.0 {Rename against procedures with static vars} {
+    proc foobar {x} {{y 10}} {
+        incr y $x
+    }
+    foobar 30
+    foobar 20
+    rename foobar barfoo
+    list [barfoo 1] [barfoo 2] [barfoo 3]
+} {61 63 66}
+
+catch {rename barfoo {}}
+
+test regression-1.1 {lrange bug with negative indexes of type int} {
+    lrange {a b c} 0 [- 0 1]
+} {}
+
+test regression-1.2 {open/close from non-global namespace} {
+       proc a::b {} {
+               set f [open $::argv0]
+               $f close
+               return $f
+       }
+       set f [a::b]
+       rename a::b ""
+       expr {$f in [info channels]}
+} {0}
+
+
+testreport
diff --git a/jim/tests/linsert.test b/jim/tests/linsert.test
new file mode 100755 (executable)
index 0000000..b528d11
--- /dev/null
@@ -0,0 +1,116 @@
+# Commands covered:  linsert
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+catch {unset lis}
+catch {rename p ""}
+
+test linsert-1.1 {linsert command} {
+    linsert {1 2 3 4 5} 0 a
+} {a 1 2 3 4 5}
+test linsert-1.2 {linsert command} {
+    linsert {1 2 3 4 5} 1 a
+} {1 a 2 3 4 5}
+test linsert-1.3 {linsert command} {
+    linsert {1 2 3 4 5} 2 a
+} {1 2 a 3 4 5}
+test linsert-1.4 {linsert command} {
+    linsert {1 2 3 4 5} 3 a
+} {1 2 3 a 4 5}
+test linsert-1.5 {linsert command} {
+    linsert {1 2 3 4 5} 4 a
+} {1 2 3 4 a 5}
+test linsert-1.6 {linsert command} {
+    linsert {1 2 3 4 5} 5 a
+} {1 2 3 4 5 a}
+test linsert-1.7 {linsert command} {
+    linsert {1 2 3 4 5} 2 one two \{three \$four
+} {1 2 one two \{three {$four} 3 4 5}
+test linsert-1.8 {linsert command} {
+    linsert {\{one \$two \{three \ four \ five} 2 a b c
+} {\{one {$two} a b c \{three { four} { five}}
+test linsert-1.9 {linsert command} {
+    linsert {{1 2} {3 4} {5 6} {7 8}} 2 {x y} {a b}
+} {{1 2} {3 4} {x y} {a b} {5 6} {7 8}}
+test linsert-1.10 {linsert command} {
+    linsert {} 2 a b c
+} {a b c}
+test linsert-1.11 {linsert command} {
+    linsert {} 2 {}
+} {{}}
+test linsert-1.12 {linsert command} {
+    linsert {a b "c c" d e} 3 1
+} {a b {c c} 1 d e}
+test linsert-1.13 {linsert command} {
+    linsert { a b c d} 0 1 2
+} {1 2 a b c d}
+test linsert-1.14 {linsert command} {
+    linsert {a b c {d e f}} 4 1 2
+} {a b c {d e f} 1 2}
+test linsert-1.15 {linsert command} {
+    linsert {a b c \{\  abc} 4 q r
+} {a b c \{\  q r abc}
+test linsert-1.16 {linsert command} {
+    linsert {a b c \{ abc} 4 q r
+} {a b c \{ q r abc}
+test linsert-1.17 {linsert command} {
+    linsert {a b c} end q r
+} {a b c q r}
+test linsert-1.18 {linsert command} {
+    linsert {a} end q r
+} {a q r}
+test linsert-1.19 {linsert command} {
+    linsert {} end q r
+} {q r}
+test linsert-1.20 {linsert command, use of end-int index} {
+    linsert {a b c d} end-2 e f
+} {a b e f c d}
+
+test linsert-2.1 {linsert errors} {
+    list [catch linsert msg] $msg
+} {1 {wrong # args: should be "linsert list index ?element ...?"}}
+test linsert-2.2 {linsert errors} {
+    list [catch {linsert a b} msg] $msg
+} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
+test linsert-2.3 {linsert errors} {
+    list [catch {linsert a 12x 2} msg] $msg
+} {1 {bad index "12x": must be integer?[+-]integer? or end?[+-]integer?}}
+test linsert-2.4 {linsert errors} tcl {
+    list [catch {linsert \{ 12 2} msg] $msg
+} {1 {unmatched open brace in list}}
+test linsert-2.5 {syntax (TIP 323)} {
+    linsert {a b c} 0
+} [list a b c]
+test linsert-2.6 {syntax (TIP 323)} {
+    linsert "a\nb\nc" 0
+} [list a b c]
+
+test linsert-3.1 {linsert won't modify shared argument objects} {
+    proc p {} {
+        linsert "a b c" 1 "x y"
+        return "a b c"
+    }
+    p
+} "a b c"
+test linsert-3.2 {linsert won't modify shared argument objects} {
+    catch {unset lis}
+    set lis [format "a \"%s\" c" "b"]
+    linsert $lis 0 [string length $lis]
+} "7 a b c"
+
+# cleanup
+catch {unset lis}
+catch {rename p ""}
+::tcltest::cleanupTests
+return
diff --git a/jim/tests/list.test b/jim/tests/list.test
new file mode 100755 (executable)
index 0000000..d4cecda
--- /dev/null
@@ -0,0 +1,113 @@
+# Commands covered:  list
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: list.test,v 1.5 2000/04/10 17:19:01 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+# First, a bunch of individual tests
+
+test list-1.1 {basic tests} {list a b c} {a b c}
+test list-1.2 {basic tests} {list {a b} c} {{a b} c}
+test list-1.3 {basic tests} {list \{a b c} {\{a b c}
+test list-1.4 {basic tests} "list a{}} b{} c}" "a\\{\\}\\} b{} c\\}"
+test list-1.5 {basic tests} {list a\[ b\] } "{a\[} b\\]"
+test list-1.6 {basic tests} {list c\  d\t } "{c } {d\t}"
+test list-1.7 {basic tests} {list e\n f\$ } "{e\n} {f\$}"
+test list-1.8 {basic tests} {list g\; h\\} {{g;} h\\}
+test list-1.9 {basic tests} "list a\\\[} b\\\]} " "a\\\[\\\} b\\\]\\\}"
+test list-1.10 {basic tests} "list c\\\} d\\t} " "c\\} d\\t\\}"
+test list-1.11 {basic tests} "list e\\n} f\\$} " "e\\n\\} f\\$\\}"
+test list-1.12 {basic tests} "list g\\;} h\\\\} " "g\\;\\} {h\\}}"
+test list-1.13 {basic tests} {list a {{}} b} {a {{}} b}
+test list-1.14 {basic tests} {list a b xy\\} "a b xy\\\\"
+test list-1.15 {basic tests} "list a b\} e\\" "a b\\} e\\\\"
+test list-1.16 {basic tests} "list a b\}\\\$ e\\\$\\" "a b\\}\\\$ e\\\$\\\\"
+test list-1.17 {basic tests} {list a\f \{\f} "{a\f} \\\{\\f"
+test list-1.18 {basic tests} {list a\r \{\r} "{a\r} \\\{\\r"
+test list-1.19 {basic tests} {list a\v \{\v} "{a\v} \\\{\\v"
+test list-1.20 {basic tests} {list \"\}\{} "\\\"\\}\\{"
+test list-1.21 {basic tests} {list a b c\\\nd} "a b c\\\\\\nd"
+test list-1.22 {basic tests} {list "{ab}\\"} \\{ab\\}\\\\
+test list-1.23 {basic tests} {list \{} "\\{"
+test list-1.24 {basic tests} {list} {}
+test list-1.25 {basic tests} {list #} {{#}}
+test list-1.26 {basic tests} {list #abc} {{#abc}}
+test list-1.27 {basic tests} {list def #abc} {def #abc}
+
+# For the next round of tests create a list and then pick it apart
+# with "index" to make sure that we get back exactly what went in.
+
+test list-2.1 {placeholder} {
+} {}
+set num 1
+proc lcheck {a b c} {
+    global num d
+    set d [list $a $b $c]
+;   test list-2.$num {what goes in must come out} {lindex $d 0} $a
+    set num [expr $num+1]
+;   test list-2.$num {what goes in must come out} {lindex $d 1} $b
+    set num [expr $num+1]
+;   test list-2.$num {what goes in must come out} {lindex $d 2} $c
+    set num [expr $num+1]
+}
+lcheck a b c
+lcheck "a b" c\td e\nf
+lcheck {{a b}} {} {  }
+lcheck \$ \$ab ab\$
+lcheck \; \;ab ab\;
+lcheck \[ \[ab ab\[
+lcheck \\ \\ab ab\\
+lcheck {"} {"ab} {ab"}
+lcheck {a b} { ab} {ab }
+lcheck a{ a{b \{ab
+lcheck a} a}b }ab
+lcheck a\\} {a \}b} {a \{c}
+lcheck xyz \\ 1\\\n2
+lcheck "{ab}\\" "{ab}xy" abc
+
+concat {}
+
+# Check that tclListObj.c's SetListFromAny handles possible overlarge
+# string rep lengths in the source object.
+
+proc slowsort list {
+    set result {}
+    set last [expr [llength $list] - 1]
+    while {$last > 0} {
+       set minIndex [expr [llength $list] - 1]
+       set min [lindex $list $last]
+       set i [expr $minIndex-1]
+       while {$i >= 0} {
+           if {[string compare [lindex $list $i] $min] < 0} {
+               set minIndex $i
+               set min [lindex $list $i]
+           }
+           set i [expr $i-1]
+       }
+       set result [concat $result [list $min]]
+       if {$minIndex == 0} {
+           set list [lrange $list 1 end]
+       } else {
+           set list [concat [lrange $list 0 [expr $minIndex-1]] \
+                         [lrange $list [expr $minIndex+1] end]]
+       }
+       set last [expr $last-1]
+    }
+    return [concat $result $list]
+}
+test list-3.1 {SetListFromAny and lrange/concat results} {
+    slowsort {fred julie alex carol bill annie}
+} {alex annie bill carol fred julie}
+
+testreport
diff --git a/jim/tests/loop.test b/jim/tests/loop.test
new file mode 100755 (executable)
index 0000000..df9001b
--- /dev/null
@@ -0,0 +1,152 @@
+source [file dirname [info script]]/testing.tcl
+
+# Check "loop" and its use of continue and break.
+needs cmd loop
+
+catch {unset a i}
+test loop-1.1 {loop tests} {
+    set a {}
+    loop i 1 6 {
+        set a [concat $a $i]
+    }
+    set a
+} {1 2 3 4 5}
+
+test loop-1.2 {loop tests} {
+    set a {}
+    loop i 1 6 {
+        if $i==4 continue
+        set a [concat $a $i]
+    }
+    set a
+} {1 2 3 5}
+
+test loop-1.3 {loop tests} {
+    set a {}
+    loop i 1 6 {
+        if $i==4 break
+        set a [concat $a $i]
+    }
+    set a
+} {1 2 3}
+
+test loop-1.5 {loop errors} {
+    catch {loop 1 2 3} msg
+} {1}
+
+test loop-1.6 {loop errors} {
+    catch {loop 1 2 3 4 5} msg
+} {1}
+
+test loop-1.7 {loop tests} {
+    set a {xyz}
+    loop i 1 6 {
+    }
+    set a
+} xyz
+
+test loop-1.8 {error in loop} {
+    set rc [catch {
+        set a {}
+        loop i 1 6 {
+            lappend a $i
+            if {$i == 3} {
+                error "stop"
+            }
+        }
+    }]
+    list $a $rc
+} {{1 2 3} 1}
+
+test loop-1.9 {loop incr} {
+    set a {}
+    loop i 0 6 2 {
+        lappend a $i
+    }
+    set a
+} {0 2 4}
+
+test loop-1.10 {no exec infinite loop} {
+    set a {}
+    loop i 0 6 -1 {
+        lappend a $i
+        break
+    }
+    set a
+} {}
+
+test loop-2.1 {loop shimmering tests} {
+    loop i 1 6 {
+    }
+    set i
+} 6
+
+test loop-2.2 {loop shimmering tests} {
+    # Setting the variable inside the loop doesn't
+    # affect the loop or the final variable value
+    loop i 1 6 {
+        set i blah
+    }
+    set i
+} 6
+
+test loop-2.3 {loop shimmering tests} {
+    set a {}
+    loop i 1 6 {
+        lappend a $i
+        set i blah
+        lappend a $i
+    }
+    set a
+} {1 blah 2 blah 3 blah 4 blah 5 blah}
+
+test loop-2.4 {loop shimmering tests} {
+    set i xyz
+    loop i 1 6 {
+    }
+    set i
+} 6
+
+test loop-2.5 {loop shimmering tests} {
+    # Ensure that the string rep of $i is updated
+    set i {1 3}
+    loop i(1) 1 6 {
+    }
+    set i
+} {1 6}
+
+test loop-2.6 {modify loop var} {
+    unset -nocomplain i
+    catch {
+        loop i(1) 1 6 {
+            # this makes it impossible to set the loop var
+            set i blah
+        }
+    }
+} 1
+
+test loop-2.7 {unset loop var} {
+    unset -nocomplain i
+    loop i 1 6 {
+        # var will simply get recreated on each loop
+        unset i
+    }
+    set i
+} 6
+
+test loop-2.8 {modify loop var} {
+    unset -nocomplain i
+    set a {}
+    loop i 1 6 {
+        lappend a $i
+        incr i
+    }
+    set a
+} {1 2 3 4 5}
+
+testreport
+break
+
+
+
+testreport
diff --git a/jim/tests/lrange.test b/jim/tests/lrange.test
new file mode 100755 (executable)
index 0000000..e72421c
--- /dev/null
@@ -0,0 +1,85 @@
+# Commands covered:  lrange
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+test lrange-1.1 {range of list elements} {
+    lrange {a b c d} 1 2
+} {b c}
+test lrange-1.2 {range of list elements} {
+    lrange {a {bcd e {f g {}}} l14 l15 d} 1 1
+} {{bcd e {f g {}}}}
+test lrange-1.3 {range of list elements} {
+    lrange {a {bcd e {f g {}}} l14 l15 d} 3 end
+} {l15 d}
+test lrange-1.4 {range of list elements} {
+    lrange {a {bcd e {f g {}}} l14 l15 d} 4 10000
+} {d}
+test lrange-1.5 {range of list elements} {
+    lrange {a {bcd e {f g {}}} l14 l15 d} 4 3
+} {}
+test lrange-1.6 {range of list elements} {
+    lrange {a {bcd e {f g {}}} l14 l15 d} 10 11
+} {}
+test lrange-1.7 {range of list elements} {
+    lrange {a b c d e} -1 2
+} {a b c}
+test lrange-1.8 {range of list elements} {
+    lrange {a b c d e} -2 -1
+} {}
+test lrange-1.9 {range of list elements} {
+    lrange {a b c d e} -2 end
+} {a b c d e}
+test lrange-1.10 {range of list elements} {
+    lrange "a b\{c d" 1 2
+} "b\\{c d"
+test lrange-1.11 {range of list elements} {
+    lrange "a b c d" end end
+} d
+test lrange-1.12 {range of list elements} {
+    lrange "a b c d" end 100000
+} d
+test lrange-1.13 {range of list elements} {
+    lrange "a b c d" end 3
+} d
+test lrange-1.14 {range of list elements} {
+    lrange "a b c d" end 2
+} {}
+test lrange-1.15 {range of list elements} {
+    concat \"[lrange {a b \{\          } 0 2]"
+} {"a b \{\ "}
+test lrange-1.16 {list element quoting} {
+    lrange {[append a .b]} 0 end    
+} {{[append} a .b\]}
+test lrange-2.1 {error conditions} {
+    list [catch {lrange a b} msg] $msg
+} {1 {wrong # args: should be "lrange list first last"}}
+test lrange-2.2 {error conditions} {
+    list [catch {lrange a b 6 7} msg] $msg
+} {1 {wrong # args: should be "lrange list first last"}}
+test lrange-2.3 {error conditions} {
+    list [catch {lrange a b 6} msg] $msg
+} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
+test lrange-2.4 {error conditions} {
+    list [catch {lrange a 0 enigma} msg] $msg
+} {1 {bad index "enigma": must be integer?[+-]integer? or end?[+-]integer?}}
+test lrange-2.5 {error conditions} tcl {
+    list [catch {lrange "a \{b c" 3 4} msg] $msg
+} {1 {unmatched open brace in list}}
+test lrange-2.6 {error conditions} tcl {
+    list [catch {lrange "a b c \{ d e" 1 4} msg] $msg
+} {1 {unmatched open brace in list}}
+
+# cleanup
+::tcltest::cleanupTests
+return
diff --git a/jim/tests/lreplace.test b/jim/tests/lreplace.test
new file mode 100755 (executable)
index 0000000..ba77505
--- /dev/null
@@ -0,0 +1,133 @@
+# Commands covered:  lreplace
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+test lreplace-1.1 {lreplace command} {
+    lreplace {1 2 3 4 5} 0 0 a
+} {a 2 3 4 5}
+test lreplace-1.2 {lreplace command} {
+    lreplace {1 2 3 4 5} 1 1 a
+} {1 a 3 4 5}
+test lreplace-1.3 {lreplace command} {
+    lreplace {1 2 3 4 5} 2 2 a
+} {1 2 a 4 5}
+test lreplace-1.4 {lreplace command} {
+    lreplace {1 2 3 4 5} 3 3 a
+} {1 2 3 a 5}
+test lreplace-1.5 {lreplace command} {
+    lreplace {1 2 3 4 5} 4 4 a
+} {1 2 3 4 a}
+test lreplace-1.6 {lreplace command} {
+    lreplace {1 2 3 4 5} 4 5 a
+} {1 2 3 4 a}
+test lreplace-1.7 {lreplace command} {
+    lreplace {1 2 3 4 5} -1 -1 a
+} {a 1 2 3 4 5}
+test lreplace-1.8 {lreplace command} {
+    lreplace {1 2 3 4 5} 2 end a b c d
+} {1 2 a b c d}
+test lreplace-1.9 {lreplace command} {
+    lreplace {1 2 3 4 5} 0 3
+} {5}
+test lreplace-1.10 {lreplace command} {
+    lreplace {1 2 3 4 5} 0 4
+} {}
+test lreplace-1.11 {lreplace command} {
+    lreplace {1 2 3 4 5} 0 1
+} {3 4 5}
+test lreplace-1.12 {lreplace command} {
+    lreplace {1 2 3 4 5} 2 3
+} {1 2 5}
+test lreplace-1.13 {lreplace command} {
+    lreplace {1 2 3 4 5} 3 end
+} {1 2 3}
+test lreplace-1.14 {lreplace command} {
+    lreplace {1 2 3 4 5} -1 4 a b c
+} {a b c}
+test lreplace-1.15 {lreplace command} {
+    lreplace {a b "c c" d e f} 3 3
+} {a b {c c} e f}
+test lreplace-1.16 {lreplace command} {
+    lreplace { 1 2 3 4 5} 0 0 a
+} {a 2 3 4 5}
+test lreplace-1.17 {lreplace command} {
+    lreplace {1 2 3 4 "5 6"} 4 4 a
+} {1 2 3 4 a}
+test lreplace-1.18 {lreplace command} {
+    lreplace {1 2 3 4 {5 6}} 4 4 a
+} {1 2 3 4 a}
+test lreplace-1.19 {lreplace command} {
+    lreplace {1 2 3 4} 2 end x y z
+} {1 2 x y z}
+test lreplace-1.20 {lreplace command} {
+    lreplace {1 2 3 4} end end a
+} {1 2 3 a}
+test lreplace-1.21 {lreplace command} {
+    lreplace {1 2 3 4} end 3 a
+} {1 2 3 a}
+test lreplace-1.22 {lreplace command} {
+    lreplace {1 2 3 4} end end
+} {1 2 3}
+test lreplace-1.23 {lreplace command} {
+    lreplace {1 2 3 4} 2 -1 xy
+} {1 2 xy 3 4}
+test lreplace-1.24 {lreplace command} {
+    lreplace {1 2 3 4} end -1 z
+} {1 2 3 z 4}
+test lreplace-1.25 {lreplace command} {
+    concat \"[lreplace {\}\     hello} end end]\"
+} {"\}\ "}
+test lreplace-1.26 {lreplace command} {
+    catch {unset foo}
+    set foo {a b}
+    list [set foo [lreplace $foo end end]] \
+        [set foo [lreplace $foo end end]] \
+        [set foo [lreplace $foo end end]]
+} {a {} {}}
+
+
+test lreplace-2.1 {lreplace errors} {
+    list [catch lreplace msg] $msg
+} {1 {wrong # args: should be "lreplace list first last ?element ...?"}}
+test lreplace-2.2 {lreplace errors} {
+    list [catch {lreplace a b} msg] $msg
+} {1 {wrong # args: should be "lreplace list first last ?element ...?"}}
+test lreplace-2.3 {lreplace errors} {
+    list [catch {lreplace x a 10} msg] $msg
+} {1 {bad index "a": must be integer?[+-]integer? or end?[+-]integer?}}
+test lreplace-2.4 {lreplace errors} {
+    list [catch {lreplace x 10 x} msg] $msg
+} {1 {bad index "x": must be integer?[+-]integer? or end?[+-]integer?}}
+test lreplace-2.5 {lreplace errors} {
+    list [catch {lreplace x 10 1x} msg] $msg
+} {1 {bad index "1x": must be integer?[+-]integer? or end?[+-]integer?}}
+test lreplace-2.6 {lreplace errors} {
+    list [catch {lreplace x 3 2} msg] $msg
+} {1 {list doesn't contain element 3}}
+test lreplace-2.7 {lreplace errors} {
+    list [catch {lreplace x 1 1} msg] $msg
+} {1 {list doesn't contain element 1}}
+
+test lreplace-3.1 {lreplace won't modify shared argument objects} {
+    proc p {} {
+        lreplace "a b c" 1 1 "x y"
+        return "a b c"
+    }
+    p
+} "a b c"
+
+# cleanup
+catch {unset foo}
+::tcltest::cleanupTests
+return
diff --git a/jim/tests/lsearch.test b/jim/tests/lsearch.test
new file mode 100755 (executable)
index 0000000..1eb6607
--- /dev/null
@@ -0,0 +1,182 @@
+# Commands covered:  lsearch
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: lsearch.test,v 1.5 2000/04/10 17:19:01 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+catch {package require regexp}
+testConstraint regexp [expr {[info commands regexp] ne {}}]
+
+set x {abcd bbcd 123 234 345}
+test lsearch-1.1 {lsearch command} {
+    lsearch $x 123
+} 2
+test lsearch-1.2 {lsearch command} {
+    lsearch $x 3456
+} -1
+test lsearch-1.3 {lsearch command} {
+    lsearch -glob $x *5
+} 4
+test lsearch-1.4 {lsearch command} {
+    lsearch -glob $x *bc*
+} 0
+
+test lsearch-2.1 {search modes} {
+    lsearch -exact {xyz bbcc *bc*} *bc*
+} 2
+test lsearch-2.2 {search modes} {
+    lsearch -exact {b.x ^bc xy bcx} ^bc
+} 1
+test lsearch-2.3 {search modes} {
+    lsearch -exact {foo bar cat} ba
+} -1
+test lsearch-2.4 {search modes} {
+    lsearch -exact {foo bar cat} bart
+} -1
+test lsearch-2.5 {search modes} {
+    lsearch -exact {foo bar cat} bar
+} 1
+test lsearch-2.6 {search modes} regexp {
+    list [catch {lsearch -regexp {xyz bbcc *bc*} *bc*} msg]
+} {1}
+test lsearch-2.7 {search modes} regexp {
+    lsearch -regexp {b.x ^bc xy bcx} ^bc
+} 3
+test lsearch-2.8 {search modes} {
+    lsearch -glob {xyz bbcc *bc*} *bc*
+} 1
+test lsearch-2.9 {search modes} {
+    lsearch -glob {b.x ^bc xy bcx} ^bc
+} 1
+test lsearch-2.10 {search modes} {
+    list [catch {lsearch -glib {b.x bx xy bcx} b.x} msg]
+} {1}
+test lsearch-2.7 {search modes, -nocase} regexp {
+    lsearch -nocase -regexp {b.x ^bc xy bcx} ^BC
+} 3
+test lsearch-2.8 {search modes, -nocase} {
+    lsearch -nocase -exact {b.x ^bc xy bcx} ^BC
+} 1
+test lsearch-2.9 {search modes, -nocase} {
+    lsearch -nocase -glob {b.x ^bc xy bcx} B*
+} 0
+
+test lsearch-3.1 {lsearch errors} {
+    list [catch lsearch msg]
+} {1}
+test lsearch-3.2 {lsearch errors} {
+    list [catch {lsearch a} msg]
+} {1}
+test lsearch-3.3 {lsearch errors} {
+    list [catch {lsearch a b c} msg]
+} {1}
+test lsearch-3.4 {lsearch errors} {
+    list [catch {lsearch a b c d} msg]
+} {1}
+
+test lsearch-4.1 {binary data} {
+    lsearch -exact [list foo one\000two bar] bar
+} 2
+test lsearch-4.2 {binary data} {
+    set x one
+    append x \x00
+    append x two
+    lsearch -exact [list foo one\000two bar] $x
+} 1
+
+test lsearch-5.1 {lsearch -all} {
+    lsearch -glob -all {a1 a2 b1 b2 a3 b3} a*
+} {0 1 4}
+
+test lsearch-5.2 {lsearch -all no match} {
+    lsearch -glob -all {a1 a2 b1 b2 a3 b3} B*
+} {}
+
+test lsearch-5.3 {lsearch -all -nocase} {
+    lsearch -glob -all -nocase {a1 a2 b1 b2 a3 b3} B*
+} {2 3 5}
+
+test lsearch-5.4 {lsearch -all -inline} {
+    lsearch -glob -all -inline -nocase {a1 a2 b1 b2 a3 b3} A*
+} {a1 a2 a3}
+
+test lsearch-5.5 {lsearch -inline} {
+    lsearch -glob -inline {a1 a2 b1 b2 a3 b3} b*
+} {b1}
+
+test lsearch-5.6 {lsearch -not -all} {
+    lsearch -not -glob -all {a1 a2 b1 b2 a3 b3} a*
+} {2 3 5}
+
+test lsearch-5.7 {lsearch -not -all no match} {
+    lsearch -not -glob -all {a1 a2 b1 b2 a3 b3} B*
+} {0 1 2 3 4 5}
+
+test lsearch-5.8 {lsearch -not -all -nocase} {
+    lsearch -not -glob -all -nocase {a1 a2 b1 b2 a3 b3} B*
+} {0 1 4}
+
+test lsearch-5.9 {lsearch -not -all -inline} {
+    lsearch -not -glob -all -inline -nocase {a1 a2 b1 b2 a3 b3} A*
+} {b1 b2 b3}
+
+test lsearch-5.10 {lsearch -not -inline} {
+    lsearch -not -glob -inline {a1 a2 b1 b2 a3 b3} b*
+} {a1}
+
+test lsearch-5.11 {lsearch -inline, no match} {
+    lsearch -glob -inline {a1 a2 b1 b2 a3 b3} C*
+} {}
+
+test lsearch-6.1 {lsearch -bool, found} jim {
+    lsearch -bool {a1 a2 b1 b2 a3 b3} b1
+} {1}
+
+test lsearch-6.2 {lsearch -bool, not found} jim {
+    lsearch -bool {a1 a2 b1 b2 a3 b3} c1
+} {0}
+
+test lsearch-6.3 {lsearch -not -bool, found} jim {
+    lsearch -not -bool {a1 a2 b1 b2 a3 b3} b1
+} {0}
+
+test lsearch-6.4 {lsearch -not -bool, not found} jim {
+    lsearch -not -bool {a1 a2 b1 b2 a3 b3} c1
+} {1}
+
+test lsearch-6.5 {lsearch -bool -all} jim {
+    lsearch -bool -glob -all {a1 a2 b1 b2 a3 b3} a*
+} {1 1 0 0 1 0}
+
+test lsearch-6.6 {lsearch -bool -all no match} jim {
+    lsearch -bool -glob -all {a1 a2 b1 b2 a3 b3} B*
+} {0 0 0 0 0 0}
+
+test lsearch-6.7 {lsearch -bool -all -nocase} jim {
+    lsearch -bool -glob -all -nocase {a1 a2 b1 b2 a3 b3} B*
+} {0 0 1 1 0 1}
+
+test lsearch-6.8 {lsearch -not -bool -all} jim {
+    lsearch -not -bool -glob -all {a1 a2 b1 b2 a3 b3} a*
+} {0 0 1 1 0 1}
+
+test lsearch-6.9 {lsearch -not -bool -all no match} jim {
+    lsearch -not -bool -glob -all {a1 a2 b1 b2 a3 b3} B*
+} {1 1 1 1 1 1}
+
+test lsearch-6.10 {lsearch -not -bool -all -nocase} jim {
+    lsearch -not -bool -glob -all -nocase {a1 a2 b1 b2 a3 b3} B*
+} {1 1 0 0 1 0}
+
+testreport
diff --git a/jim/tests/lsort.test b/jim/tests/lsort.test
new file mode 100755 (executable)
index 0000000..9d8ff86
--- /dev/null
@@ -0,0 +1,219 @@
+# This file contains a collection of tests for the procedures in the
+# file tclCmdIL.c.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: lsort.test,v 1.12.2.2 2001/10/08 15:50:24 dkf Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+test lsort-1.1 {Tcl_LsortObjCmd procedure} jim {
+    list [catch {lsort} msg] $msg
+} {1 {wrong # args: should be "lsort ?options? list"}}
+test lsort-1.2 {Tcl_LsortObjCmd procedure} jim {
+    list [catch {lsort -foo {1 3 2 5}} msg] $msg
+} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -increasing, -index, -integer, -nocase, -real, or -unique}}
+test lsort-1.3 {Tcl_LsortObjCmd procedure, default options} {
+    lsort {d e c b a \{ d35 d300}
+} {a b c d d300 d35 e \{}
+test lsort-1.4 {Tcl_LsortObjCmd procedure, -ascii option} {
+    lsort -integer -ascii {d e c b a d35 d300}
+} {a b c d d300 d35 e}
+test lsort-1.5 {Tcl_LsortObjCmd procedure, -command option} {
+    list [catch {lsort -command {1 3 2 5}} msg] $msg
+} {1 {"-command" option must be followed by comparison command}}
+test lsort-1.6 {Tcl_LsortObjCmd procedure, -command option} {
+    proc cmp {a b} {
+               set rc [expr {[string match x* $b] - [string match x* $a]}]
+               if {$rc == 0} {
+                       set rc [string compare $a $b]
+               }
+               return $rc
+    }
+    lsort -command cmp {x1 abc x2 def x3 x4}
+} {x1 x2 x3 x4 abc def}
+test lsort-1.7 {Tcl_LsortObjCmd procedure, -decreasing option} {
+    lsort -decreasing {d e c b a d35 d300}
+} {e d35 d300 d c b a}
+test lsort-1.8 {Tcl_LsortObjCmd procedure, -real option} {
+    lsort -real {24.2 6e3 150e-1}
+} {150e-1 24.2 6e3}
+test lsort-1.10 {Tcl_LsortObjCmd procedure, -increasing option} {
+    lsort -decreasing -increasing {d e c b a d35 d300}
+} {a b c d d300 d35 e}
+test lsort-1.11 {Tcl_LsortObjCmd procedure, -index option} {
+    list [catch {lsort -index {1 3 2 5}} msg] $msg
+} {1 {"-index" option must be followed by list index}}
+test lsort-1.12 {Tcl_LsortObjCmd procedure, -index option} {
+    list [catch {lsort -index foo {1 3 2 5}} msg] $msg
+} {1 {bad index "foo": must be integer?[+-]integer? or end?[+-]integer?}}
+test lsort-1.13 {Tcl_LsortObjCmd procedure, -index option} {
+    lsort -index end -integer {{2 25} {10 20 50 100} {3 16 42} 1}
+} {1 {2 25} {3 16 42} {10 20 50 100}}
+test lsort-1.14 {Tcl_LsortObjCmd procedure, -index option} {
+    lsort -index 1 -integer {{1 25 100} {3 16 42} {10 20 50}}
+} {{3 16 42} {10 20 50} {1 25 100}}
+test lsort-1.15 {Tcl_LsortObjCmd procedure, -integer option} {
+    lsort -integer {24 6 300 18}
+} {6 18 24 300}
+test lsort-1.16 {Tcl_LsortObjCmd procedure, -integer option} {
+    list [catch {lsort -integer {1 3 2.4}} msg] $msg
+} {1 {expected integer but got "2.4"}}
+test lsort-1.19 {Tcl_LsortObjCmd procedure, empty list} {
+    lsort {}
+} {}
+test lsort-1.24 {Tcl_LsortObjCmd procedure, order of -index and -command} {
+    catch {rename 1 ""}
+    proc testcmp {a b} {return [string compare $a $b]}
+    set l [list [list a b] [list c d]]
+    set result [list [catch {lsort -command testcmp -index 1 $l} msg] $msg]
+    rename testcmp ""
+    set result
+} [list 0 [list [list a b] [list c d]]]
+test lsort-1.25 {Tcl_LsortObjCmd procedure, order of -index and -command} {
+    catch {rename 1 ""}
+    proc testcmp {a b} {return [string compare $a $b]}
+    set l [list [list a b] [list c d]]
+    set result [list [catch {lsort -index 1 -command testcmp $l} msg] $msg]
+    rename testcmp ""
+    set result
+} [list 0 [list [list a b] [list c d]]]
+# Note that the required order only exists in the end-1'th element;
+# indexing using the end element or any fixed offset from the start
+# will not work...
+test lsort-1.26 {Tcl_LsortObjCmd procedure, offset indexing from end} {
+    lsort -index end-1 {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}}
+} {{c 4 5 6 d h} {a 1 e i} {b 2 3 f g}}
+
+# Can't think of any good tests for the MergeSort and MergeLists
+# procedures, except a bunch of random lists to sort.
+
+test lsort-2.1 {MergeSort and MergeLists procedures} {
+    set result {}
+    set r 1435753299
+    proc rand {} {
+       global r
+       set r [expr {(16807 * $r) % (0x7fffffff)}]
+    }
+    for {set i 0} {$i < 150} {incr i} {
+       set x {}
+       for {set j 0} {$j < $i} {incr j} {
+           lappend x [expr {[rand] & 0xfff}]
+       }
+       set y [lsort -integer $x]
+       set old -1
+       foreach el $y {
+           if {$el < $old} {
+               append result "list {$x} sorted to {$y}, element $el out of order\n"
+               break
+           }
+           set old $el
+       }
+    }
+    set result
+} {}
+
+test lsort-3.1 {SortCompare procedure, skip comparisons after error} {
+    set x 0
+    proc cmp {a b} {
+       global x
+       incr x
+       error "error #$x"
+    }
+    list [catch {lsort -integer -command cmp {48 6 28 190 16 2 3 6 1}} msg] \
+           $msg $x
+} {1 {error #1} 1}
+test lsort-3.2 {lsort -real, returning indices} {
+    lsort -decreasing -real {1.2 34.5 34.5 5.6}
+} {34.5 34.5 5.6 1.2}
+test lsort-3.3 {SortCompare procedure, -index option} jim {
+    list [catch {lsort -integer -index 2 {{20 10} {15 30 40}}} msg] $msg
+} {1 {list index out of range}}
+test lsort-3.5 {SortCompare procedure, -index option} jim {
+    list [catch {lsort -integer -index 2 {{20 10 13} {15}}} msg] $msg
+} {1 {list index out of range}}
+test lsort-3.6 {SortCompare procedure, -index option} {
+    lsort -integer -index 2 {{1 15 30} {2 5 25} {3 25 20}}
+} {{3 25 20} {2 5 25} {1 15 30}}
+test lsort-3.7 {SortCompare procedure, -ascii option} {
+    lsort -ascii {d e c b a d35 d300 100 20}
+} {100 20 a b c d d300 d35 e}
+test lsort-3.9 {SortCompare procedure, -integer option} {
+    list [catch {lsort -integer {x 3}} msg] $msg
+} {1 {expected integer but got "x"}}
+test lsort-3.10 {SortCompare procedure, -integer option} {
+    list [catch {lsort -integer {3 q}} msg] $msg
+} {1 {expected integer but got "q"}}
+test lsort-3.11 {SortCompare procedure, -integer option} {
+    lsort -integer {35 21 0x20 30 023 100 8}
+} {8 21 023 30 0x20 35 100}
+test lsort-3.15 {SortCompare procedure, -command option} {
+    proc cmp {a b} {
+       error "comparison error"
+    }
+    list [catch {lsort -command cmp {48 6}} msg] $msg
+} {1 {comparison error}}
+test lsort-3.16 {SortCompare procedure, -command option, long command} {
+    proc cmp {dummy a b} {
+       string compare $a $b
+    }
+    lsort -command {cmp {this argument is very very long in order to make the dstring overflow its statically allocated space}} {{this first element is also long in order to help expand the dstring} {the second element, last but not least, is quite long also, in order to make absolutely sure that space is allocated dynamically for the dstring}}
+} {{the second element, last but not least, is quite long also, in order to make absolutely sure that space is allocated dynamically for the dstring} {this first element is also long in order to help expand the dstring}}
+test lsort-3.17 {SortCompare procedure, -command option, non-integer result} jim {
+    proc cmp {a b} {
+       return foow
+    }
+    list [catch {lsort -command cmp {48 6}} msg] $msg
+} {1 {expected integer but got "foow"}}
+test lsort-3.18 {SortCompare procedure, -command option} {
+    proc cmp {a b} {
+       expr {$b - $a}
+    }
+    lsort -command cmp {48 6 18 22 21 35 36}
+} {48 36 35 22 21 18 6}
+test lsort-3.19 {SortCompare procedure, -decreasing option} {
+    lsort -decreasing -integer {35 21 0x20 30 023 100 8}
+} {100 35 0x20 30 023 21 8}
+test lsort-3.20 {SortCompare procedure, -real option} -body {
+    lsort -real {6...4 3}
+} -returnCodes error -result {expected number but got "6...4"}
+test lsort-3.21 {lsort, unique sort} {
+    lsort -integer -unique {3 1 2 3 1 4 3}
+} {1 2 3 4}
+test lsort-3.22 {lsort, unique sort with index} {
+    # lsort -unique should return the last unique item
+       # Note that lsort is not guarunteed to be a stable sort, so
+       # allow for different 
+    lsort -int -unique {0 5 05 00 004 4}
+} {00 4 05}
+
+test lsort-4.26 {DefaultCompare procedure, signed characters} utf8 {
+    set l [lsort [list "abc\u80" "abc"]]
+    set viewlist {}
+    foreach s $l {
+       set viewelem ""
+       set len [string length $s]
+       for {set i 0} {$i < $len} {incr i} {
+           set c [string index $s $i]
+           scan $c %c d
+           if {$d > 0 && $d < 128} {
+               append viewelem $c
+           } else {
+               append viewelem "\\[format %03o [expr {$d & 0xff}]]"
+           }
+       }
+       lappend viewlist $viewelem
+    }
+    set viewlist
+} [list "abc" "abc\\200"]
+
+test lsort-5.1 "Sort case insensitive" {
+    lsort -nocase {ba aB aa ce}
+} {aa aB ba ce}
+
+testreport
diff --git a/jim/tests/lsortcmd.test b/jim/tests/lsortcmd.test
new file mode 100755 (executable)
index 0000000..ed53fe5
--- /dev/null
@@ -0,0 +1,32 @@
+source [file dirname [info script]]/testing.tcl
+
+set list {b d a c z}
+
+proc sorter {a v1 v2} {
+       set ::arg $a
+       return [string compare $v1 $v2]
+}
+
+proc test_lsort_cmd {test cmd list exp} {
+       lsort -command $cmd $list
+       if {$::arg != $exp} {
+               error "$test: Failed"
+       }
+}
+
+test lsortcmd-1.1 "Sort with one arg" {
+       lsort -command "sorter arg1" $list
+       set arg
+} {arg1}
+
+test lsortcmd-1.2 "Sort with one arg containg spaces" {
+       lsort -command {sorter "arg with space"} $list
+       set arg
+} {arg with space}
+
+test lsortcmd-1.3 "Sort with arg as list containg spaces" {
+       lsort -command [list sorter [list arg with list "last with spaces"]] $list
+       set arg
+} {arg with list {last with spaces}}
+
+testreport
diff --git a/jim/tests/misc.test b/jim/tests/misc.test
new file mode 100755 (executable)
index 0000000..9a9ac35
--- /dev/null
@@ -0,0 +1,569 @@
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+needs cmd gets tclcompat
+needs cmd array
+
+catch {unset a b}
+test regr-1.1 "Double dereference arrays" {
+       array set a {one ONE two TWO three THREE}
+       array set b {ONE 1 TWO 2 THREE 3}
+       set chan two
+       set b($a($chan))
+} {2}
+
+# Will assert on exit if the bug exists
+test regr-1.2 "Reference count shared literals" {
+       proc a {} {
+               while {1} {break}
+       }
+       a
+       rename a ""
+       return 1
+} {1}
+
+test regr-1.3 "Invalid for expression" jim {
+       # Crashes with invalid expression
+       catch {
+               for {set i 0} {$i < n} {incr i} {
+                       set a(b) $i
+                       set a(c) $i
+                       break
+               }
+       }
+} 1
+
+test regr-1.4 "format double percent" {
+       format (%d%%) 12
+} {(12%)}
+
+test regr-1.5 "lassign with empty list" {
+       unset -nocomplain a b c
+       lassign {} a b c
+       info exists c
+} {1}
+
+test io-1.1 "Read last line with no newline" {
+       set lines 0
+       set f [open $testdir/testio.in]
+       while {[gets $f buf] >= 0} {
+               incr lines
+       }
+       close $f
+       list $lines
+} {2}
+
+set g1 1
+set g2 2
+array set g3 {4 5 6 7}
+
+proc test_unset {} {
+       test unset-1.1 "Simple var" {
+               set g4 4
+               list [catch {unset g4; info exists g4} msg] $msg
+       } {0 0}
+
+       test unset-1.2 "Simple var" {
+               list [catch {unset g4; info exists g4} msg] $msg
+       } {1 {can't unset "g4": no such variable}}
+
+       test unset-1.3 "Simple var" {
+               list [catch {unset g2; info exists g2} msg] $msg
+       } {1 {can't unset "g2": no such variable}}
+
+       test unset-1.4 "Global via global" {
+               global g1
+               list [catch {unset g1; info exists g1} msg] $msg
+       } {0 0}
+
+       test unset-1.5 "Global error" {
+               list [catch {unset ::g2; info exists ::g2} msg] $msg
+       } {0 0}
+
+       test unset-1.6 "Global array" {
+               list [catch {unset ::g3; info exists ::g3} msg] $msg
+       } {0 0}
+
+       test unset-1.7 "Simple var -nocomplain" {
+               list [catch {unset -nocomplain g2; info exists g2} msg] $msg
+       } {0 0}
+
+       test unset-1.8 "Simple var --" {
+               list [catch {unset -- g2; info exists g2} msg] $msg
+       } {1 {can't unset "g2": no such variable}}
+
+       test unset-1.9 "Simple var -nocomplain --" {
+               set g2 1
+               list [catch {unset -nocomplain -- g2; info exists g2} msg] $msg
+       } {0 0}
+
+       test unset-1.10 "Var named -nocomplain with --" {
+               set -nocomplain 1
+               list [catch {unset -- -nocomplain; info exists -nocomplain} msg] $msg
+       } {0 0}
+
+       test unset-1.11 "Unset no args" {
+               list [catch {unset} msg] $msg
+       } {0 {}}
+}
+
+test_unset
+
+test lrepeat-1.1 "Basic tests" {
+       lrepeat 1 a
+} {a}
+
+test lrepeat-1.2 "Basic tests" {
+       lrepeat 1 a b
+} {a b}
+
+test lrepeat-1.3 "Basic tests" {
+       lrepeat 2 a b
+} {a b a b}
+
+test lrepeat-1.4 "Basic tests" {
+       lrepeat 2 a
+} {a a}
+
+test lrepeat-1.5 "Errors" {
+       catch {lrepeat}
+} {1}
+
+test lrepeat-1.6 "Errors" {
+       lrepeat 1
+} {}
+
+test lrepeat-1.7 "Errors" {
+       lrepeat 0 a b
+} {}
+
+test lrepeat-1.8 "Errors" {
+       catch {lrepeat -10 a}
+} {1}
+
+test lindex-1.1 "Integer" {
+       lindex {a b c} 0
+} a
+
+test lindex-1.2 "Integer" {
+       lindex {a b c} 2
+} c
+
+test lindex-1.3 "Integer" {
+       lindex {a b c} -1
+} {}
+
+test lindex-1.4 "Integer" {
+       lindex {a b c} 4
+} {}
+
+test lindex-1.5 "end" {
+       lindex {a b c} end
+} c
+
+test lindex-1.6 "end" {
+       lindex {a b c} end-1
+} b
+
+test lindex-1.7 "end" {
+       lindex {a b c} end-4
+} {}
+
+test lindex-1.8 "end + " {
+       lindex {a b c} end+1
+} {}
+
+test lindex-1.9 "end + " {
+       lindex {a b c} end+-1
+} b
+
+test lindex-1.10 "end - errors" {
+       catch {lindex {a b c} end-}
+} 1
+
+test lindex-1.11 "end - errors" {
+       catch {lindex {a b c} end-blah}
+} 1
+
+test lindex-1.12 "int+int, int-int" {
+       lindex {a b c} 0+4
+} {}
+
+test lindex-1.13 "int+int, int-int" {
+       lindex {a b c} 3-1
+} c
+
+test lindex-1.14 "int+int, int-int" {
+       lindex {a b c} 1--1
+} c
+
+test lindex-1.15 "int+int, int-int" {
+       set l {a b c}
+       lindex $l [lsearch $l b]-1
+} a
+
+test lindex-1.16 "int+int, int-int" {
+       lindex {a b c} 0+1
+} b
+
+test lindex-1.17 "int+int - errors" {
+       catch {lindex {a b c} 5-blah}
+} 1
+
+test lindex-1.18 "int+int - errors" {
+       catch {lindex {a b c} blah-2}
+} 1
+
+test lindex-1.19 "int+int - errors" {
+       catch {lindex {a b c} 5+blah}
+} 1
+
+test lindex-1.20 "unary plus" {
+       lindex {a b c} +2
+} c
+
+test incr-1.1 "incr unset" {
+       unset -nocomplain a
+       incr a
+       set a
+} 1
+
+test incr-1.2 "incr, incr unset" {
+       incr a
+} 2
+
+test incr-1.3 "incr unset array element" {
+       unset -nocomplain a
+       incr a(2)
+       set a(2)
+} 1
+
+test incr-1.4 "incr array element - shimmering" {
+       set b "$a(2)-test"
+       incr a(2)
+} 2
+
+test catch-1.1 "catch ok" {
+       list [catch {set abc 2} result] $result
+} {0 2}
+
+test catch-1.2 "catch error" {
+       list [catch {error 3} result] $result
+} {1 3}
+
+test catch-1.3 "catch break" {
+       list [catch {break} result] $result
+} {3 {}}
+
+test catch-1.4 "catch -nobreak" {
+       set result {}
+       foreach x {a b c} {
+               lappend result $x
+               # This acts just like break since it won't be caught by catch
+               catch -nobreak {break} tmp
+       }
+       set result
+} {a}
+
+test catch-1.5 "catch -no3" {
+       set result {}
+       foreach x {a b c} {
+               lappend result $x
+               # Same as above, but specify as an integer
+               catch -no3 {break} tmp
+       }
+       set result
+} {a}
+
+test catch-1.6 "catch break" {
+       set result {}
+       foreach x {a b c} {
+               lappend result $x
+               # This does nothing since the break is caught
+               catch {break} tmp
+       }
+       set result
+} {a b c}
+
+
+test catch-1.7 "catch exit" {
+       # Normally exit would not be caught
+       dict get [info returncodes] [catch -exit {exit 5} result]
+} {exit}
+
+test catch-1.8 "catch error has -errorinfo" {
+       set rc [catch {set undefined} msg opts]
+       list $rc [info exists opts(-errorinfo)]
+} {1 1}
+
+test catch-1.9 "catch no error has no -errorinfo" {
+       set rc [catch {set x 1} msg opts]
+       list $rc [info exists opts(-errorinfo)]
+} {0 0}
+
+test return-1.1 "return can rethrow an error" {
+       proc a {} { error "from a" }
+       proc b {} { catch {a} msg opts; return {*}$opts $msg }
+       set rc [catch {b} msg opts]
+       list $rc $msg [llength $opts(-errorinfo)]
+} {1 {from a} 6}
+
+test return-1.2 "error can rethrow an error" {
+       proc a {} { error "from a" }
+       proc b {} { catch {a} msg; error $msg [info stacktrace] }
+       set rc [catch {b} msg opts]
+       list $rc $msg [llength $opts(-errorinfo)]
+} {1 {from a} 9}
+
+test return-1.3 "return can rethrow no error" {
+       proc a {} { return "from a" }
+       proc b {} { catch {a} msg opts; return {*}$opts $msg }
+       set rc [catch {b} msg opts]
+       #list $rc $msg [llength $opts(-errorinfo)]
+       list $rc $msg [info exists opts(-errorinfo)]
+} {0 {from a} 0}
+
+test stringreverse-1.1 "Containing nulls" {
+       string reverse abc\0def
+} "fed\0cba"
+
+test split-1.1 "Split with leading null" {
+       split "\0abc\0def\0" \0
+} {{} abc def {}}
+
+test parsevar-1.1 "Variables should include double colons" {
+       set ::a::b 2
+       set x $::a::b
+       unset ::a::b
+       set x
+} 2
+
+test sharing-1.1 "Problems with ref sharing in arrays: lappend" {
+       set a {a 1 c 2}
+       set b $a
+       lappend b(c) 3
+       set a(c)
+} 2
+
+test sharing-1.2 "Problems with ref sharing in arrays: append" {
+       set a {a 1 c 2}
+       set b $a
+       append b(c) 3
+       set a(c)
+} 2
+
+test sharing-1.3 "Problems with ref sharing in arrays: incr" {
+       set a {a 1 c 2}
+       set b $a
+       incr b(c)
+       set a(c)
+} 2
+
+test sharing-1.4 "Problems with ref sharing in arrays: lset" {
+       set a {a 1 c {2 3}}
+       set b $a
+       lset b(c) 1 x
+       set a(c)
+} {2 3}
+
+test jimexpr-1.1 "integer ** operator" {
+    expr {2 ** 3}
+} 8
+
+test jimexpr-1.2 "integer ** operator" {
+    expr {0 ** 3}
+} 0
+
+test jimexpr-1.3 "integer ** operator" {
+    expr {2 ** 0}
+} 1
+
+test jimexpr-1.4 "integer ** operator" {
+    expr {-2 ** 1}
+} -2
+
+test jimexpr-1.5 "integer ** operator" {
+    expr {3 ** -2}
+} 0
+
+test jimexpr-1.6 "+ command" {
+    + 1
+} 1
+
+test jimexpr-1.7 "+ command" {
+    + 2 3.5
+} 5.5
+
+test jimexpr-1.8 "+ command" {
+    + 2 3 4 -6
+} 3
+
+test jimexpr-1.9 "* command" {
+    * 4
+} 4
+
+test jimexpr-1.10 "* command" {
+    * 4 2
+} 8
+
+test jimexpr-1.11 "* command" {
+    * 4 2 -0.5
+} -4.0
+
+test jimexpr-1.12 "/ command" {
+    / 2
+} 0.5
+
+test jimexpr-1.12 "/ command" {
+    / 0.5
+} 2.0
+
+test jimexpr-1.13 "/ command" {
+    / 12 3
+} 4
+
+test jimexpr-1.14 "/ command" {
+    / 12 3 2.0
+} 2.0
+
+test jimexpr-1.15 "- command" {
+    - 6
+} -6
+
+test jimexpr-1.15 "- command" {
+    - 6.5
+} -6.5
+
+test jimexpr-1.16 "- command" {
+    - 6 3
+} 3
+
+test jimexpr-1.17 "- command" {
+    - 6 3 1.5
+} 1.5
+
+test jimexpr-1.17 "- command" {
+    - 6.5 3
+} 3.5
+
+test jimexpr-2.1 "errors in math commands" {
+    list [catch /] [catch {/ x}] [catch -] [catch {- blah blah}] [catch {- 2.0 blah}] [catch {+ x y}] [catch {* x}]
+} {1 1 1 1 1 1 1}
+
+test jimexpr-2.2 "not var optimisation" {
+       set x [expr 1]
+       set y [expr 0]
+       set z [expr 2.0]
+       list [expr {!$x}] [expr {!$y}] [expr {!$z}]
+} {0 1 0}
+
+test jimexpr-2.3 "expr access unset var" {
+       unset -nocomplain a
+       catch {expr {3 * $a}}
+} 1
+
+test jimexpr-2.4 "expr double as bool" {
+       set x 2
+       if {1.0} {
+               set x 3
+       }
+} 3
+
+# May be supported if support compiled in
+test jimexpr-2.5 "double ** operator" {
+    catch {expr {2.0 ** 3}} result
+    expr {$result in {unsupported 8.0}}
+} 1
+
+# This one is for test coverage of an unusual case
+test jimobj-1.1 "duplicate obj with no dupIntRepProc" {
+       proc "x x" {} { return 2 }
+       set a "x x"
+       # force it to be a command object
+       set b [$a]
+       # A second reference
+       set c $a
+       # Now force it to be duplicated
+       lset a 1 x
+       # force the duplicate object it to be a command object again
+       set b [$a]
+       # And get the string rep
+       set x "y $a"
+} "y x x"
+
+test jimobj-1.2 "cooerced double to int" {
+       set x 3
+       # cooerce to a double
+       expr {4.5 + $x}
+       # Now get the int rep
+       incr x
+} 4
+
+test jimobj-1.3 "cooerced double to double" {
+       set x 3
+       # cooerce to a double
+       expr {4.5 + $x}
+       # Now use as a double
+       expr {1.5 + $x}
+} 4.5
+
+test jimobj-1.4 "incr dict sugar" {
+       unset -nocomplain a
+       set a(3) 3
+       incr a(3)
+       list $a(3) $a
+} {4 {3 4}}
+
+test jim-badvar-1.1 "invalid variable name" {
+       set x b\0c
+       catch {set $x 5}
+} 1
+
+test jim-badvar-1.2 "incr invalid variable name" {
+       set x b\0c
+       catch {incr $x}
+} 1
+
+test lset-1.1 "lset with bad var" {
+       catch {lset badvar 1 x}
+} 1
+
+test dict-1.1 "dict to string" {
+       set a [dict create abc \\ def \"]
+       set x x$a
+       # The order of keys in the dictionary is random
+       if {$x eq "xabc \\\\ def {\"}" || $x eq "xdef {\"} abc \\\\"} {
+               return ok
+       } else {
+               return "failed: \"$x\""
+       }
+} ok
+
+test channels-1.1 {info channels} {
+       lsort [info channels]
+} {stderr stdin stdout}
+
+test lmap-1.1 {lmap} {
+       lmap p {1 2 3} {incr p}
+} {2 3 4}
+
+test exprerr-1.1 {Error message with bad expr} {
+       catch {expr {5 ||}} msg
+       set msg
+} {Expression has bad operands to ||}
+
+test eval-list-1.1 {Lost string rep with list} {
+       set x {set y 1; incr y}
+       # Convert to list rep internally
+       lindex $x 4
+       # But make sure we don't lost the original string rep
+       list [catch $x] $y
+} {0 2}
+
+test info-statics-1.1 {info statics commands} {
+       set x 1
+       proc a {} {x {y 2}} {}
+       lsort [info statics a]
+} {1 2 x y}
+
+testreport
diff --git a/jim/tests/namespace.test b/jim/tests/namespace.test
new file mode 100755 (executable)
index 0000000..98acf3e
--- /dev/null
@@ -0,0 +1,499 @@
+source [file dirname [info script]]/testing.tcl
+needs cmd namespace
+
+test namespace-1.1 {usage for "namespace" command} -body {
+    namespace
+} -returnCodes error -match glob -result {wrong # args: should be *}
+
+test namespace-1.2 {global namespace's name is "::" or {}} {
+    list [namespace current] [namespace eval {} {namespace current}] [namespace eval :: {namespace current}]
+} {:: :: ::}
+
+test namespace-1.3 {usage for "namespace eval"} -body {
+    namespace eval
+} -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"}
+
+test namespace-1.5 {access a new namespace} {
+    namespace eval ns1 { namespace current }
+} {::ns1}
+
+test namespace-1.7 {usage for "namespace eval"} -body {
+    namespace eval ns1
+} -returnCodes error -match glob -result {wrong # args: should be "namespace eval *"}
+
+test namespace-1.8 {command "namespace eval" concatenates args} {
+    namespace eval ns1 namespace current
+} {::ns1}
+
+test namespace-1.9 {simple namespace elements} {
+    namespace eval ns1 {
+        variable v1 1
+        proc p1 {a} {variable v1; list $a $v1}
+        p1 3
+    }
+} {3 1}
+
+test namespace-1.10 {commands in a namespace} {
+    namespace eval ns1 {
+        info commands [namespace current]::*
+    }
+} {::ns1::p1}
+
+test namespace-1.11 {variables in a namespace} {
+    namespace eval ns1 {
+        info vars [namespace current]::*
+    }
+} {::ns1::v1}
+
+test namespace-1.12 {global vars are separate from locals vars} {
+    set v1 2
+    list [ns1::p1 123] [set ns1::v1] [set ::v1]
+} {{123 1} 1 2}
+
+test namespace-1.13 {add to an existing namespace} {
+    namespace eval ns1 {
+        variable v2 22
+        proc p2 {script} {variable v2; eval $script}
+        p2 {return $v2}
+    }
+} 22
+
+test namespace-1.14 {commands in a namespace} {
+    lsort [namespace eval ns1 {info commands [namespace current]::*}]
+} {::ns1::p1 ::ns1::p2}
+
+test namespace-1.15 {variables in a namespace} {
+    lsort [namespace eval ns1 {info vars [namespace current]::*}]
+} {::ns1::v1 ::ns1::v2}
+
+# Tcl produces fully scoped names here
+test namespace-1.16 {variables in a namespace} jim {
+    lsort [info vars ns1::*]
+} {ns1::v1 ns1::v2}
+
+test namespace-1.17 {commands in a namespace are hidden} -body {
+    v2 {return 3}
+} -returnCodes error -result {invalid command name "v2"}
+
+test namespace-1.18 {using namespace qualifiers} {
+    ns1::p2 {return 44}
+} 44
+
+test namespace-1.19 {using absolute namespace qualifiers} {
+    ::ns1::p2 {return 55}
+} 55
+
+test namespace-1.20 {variables in a namespace are hidden} -body {
+    set v2
+}  -returnCodes error -result {can't read "v2": no such variable}
+
+test namespace-1.21 {using namespace qualifiers} {
+    list $ns1::v1 $ns1::v2
+} {1 22}
+
+test namespace-1.22 {using absolute namespace qualifiers} {
+    list $::ns1::v1 $::ns1::v2
+} {1 22}
+
+test namespace-1.23 {variables can be accessed within a namespace} {
+    ns1::p2 {
+        variable v1
+        variable v2
+        list $v1 $v2
+    }
+} {1 22}
+
+test namespace-1.24 {setting global variables} {
+    ns1::p2 {
+               variable v1
+        set v1 new
+    }
+    namespace eval ns1 {
+        variable v1
+        variable v2
+        list $v1 $v2
+    }
+} {new 22}
+
+test namespace-1.25 {qualified variables don't need a global declaration} {
+    namespace eval ns2 { variable x 456 }
+    set cmd {set ::ns2::x}
+    ns1::p2 "$cmd some-value"
+       set ::ns2::x
+} {some-value}
+
+test namespace-1.26 {namespace qualifiers are okay after $'s} {
+    namespace eval ns1 { variable x; variable y; set x 12; set y 34 }
+    set cmd {list $::ns1::x $::ns1::y}
+    list [ns1::p2 $cmd] [eval $cmd]
+} {{12 34} {12 34}}
+
+test namespace-1.27 {can create commands with null names} {
+    proc ns1:: {args} {return $args}
+       ns1:: x
+} {x}
+
+test namespace-1.28 {namespace variable with array element syntax} -body {
+       namespace eval ns1 {
+               variable x(3) y
+       }
+} -returnCodes error -result {can't define "x(3)": name refers to an element in an array}
+
+unset -nocomplain ns1::x ns1::y
+
+# -----------------------------------------------------------------------
+# TEST: using "info" in namespace contexts
+# -----------------------------------------------------------------------
+test namespace-2.1 {querying:  info commands} {
+    lsort [ns1::p2 {info commands [namespace current]::*}]
+} {::ns1:: ::ns1::p1 ::ns1::p2}
+
+test namespace-2.2 {querying:  info procs} {
+    lsort [ns1::p2 {info procs}]
+} {{} p1 p2}
+
+# Tcl produces fully scoped names here
+test namespace-2.3 {querying:  info vars} jim {
+    lsort [info vars ns1::*]
+} {ns1::v1 ns1::v2}
+
+test namespace-2.4 {querying:  info vars} {
+    lsort [ns1::p2 {info vars [namespace current]::*}]
+} {::ns1::v1 ::ns1::v2}
+
+test namespace-2.5 {querying:  info locals} {
+    lsort [ns1::p2 {info locals}]
+} {script}
+
+test namespace-2.6 {querying:  info exists} {
+    ns1::p2 {info exists v1}
+} {0}
+
+test namespace-2.7 {querying:  info exists} {
+    ns1::p2 {info exists v2}
+} {1}
+
+test namespace-2.8 {querying:  info args} {
+    info args ns1::p2
+} {script}
+
+test namespace-2.9 {querying:  info body} {
+    string trim [info body ns1::p1]
+} {variable v1; list $a $v1}
+
+# -----------------------------------------------------------------------
+# TEST: namespace qualifiers, namespace tail
+# -----------------------------------------------------------------------
+test namespace-3.1 {usage for "namespace qualifiers"} {
+    list [catch "namespace qualifiers" msg] $msg
+} {1 {wrong # args: should be "namespace qualifiers string"}}
+
+test namespace-3.2 {querying:  namespace qualifiers} {
+    list [namespace qualifiers ""] \
+         [namespace qualifiers ::] \
+         [namespace qualifiers x] \
+         [namespace qualifiers ::x] \
+         [namespace qualifiers foo::x] \
+         [namespace qualifiers ::foo::bar::xyz]
+} {{} {} {} {} foo ::foo::bar}
+
+test namespace-3.3 {usage for "namespace tail"} {
+    list [catch "namespace tail" msg] $msg
+} {1 {wrong # args: should be "namespace tail string"}}
+
+test namespace-3.4 {querying:  namespace tail} {
+    list [namespace tail ""] \
+         [namespace tail ::] \
+         [namespace tail x] \
+         [namespace tail ::x] \
+         [namespace tail foo::x] \
+         [namespace tail ::foo::bar::xyz]
+} {{} {} x x x xyz}
+
+# -----------------------------------------------------------------------
+# TEST: namespace hierarchy
+# -----------------------------------------------------------------------
+test namespace-5.1 {define nested namespaces} {
+    set test_ns_var_global "var in ::"
+    proc test_ns_cmd_global {} {return "cmd in ::"}
+    namespace eval nsh1 {
+        set test_ns_var_hier1 "particular to hier1"
+        proc test_ns_cmd_hier1 {} {return "particular to hier1"}
+        proc test_ns_show {} {return "[namespace current]: 1"}
+        namespace eval nsh2 {
+            set test_ns_var_hier2 "particular to hier2"
+            proc test_ns_cmd_hier2 {} {return "particular to hier2"}
+            proc test_ns_show {} {return "[namespace current]: 2"}
+            namespace eval nsh3a {}
+            namespace eval nsh3b {}
+        }
+        namespace eval nsh2a {}
+        namespace eval nsh2b {}
+    }
+} {}
+
+test namespace-5.2 {namespaces can be nested} {
+    list [namespace eval nsh1 {namespace current}] \
+         [namespace eval nsh1 {
+              namespace eval nsh2 {namespace current}
+          }]
+} {::nsh1 ::nsh1::nsh2}
+
+test namespace-5.3 {namespace qualifiers work in namespace command} {
+    list [namespace eval ::nsh1 {namespace current}] \
+         [namespace eval nsh1::nsh2 {namespace current}] \
+         [namespace eval ::nsh1::nsh2 {namespace current}]
+} {::nsh1 ::nsh1::nsh2 ::nsh1::nsh2}
+
+test namespace-5.4 {nested namespaces can access global namespace} {
+    list [namespace eval nsh1 {set ::test_ns_var_global}] \
+         [namespace eval nsh1 {test_ns_cmd_global}] \
+         [namespace eval nsh1::nsh2 {set ::test_ns_var_global}] \
+         [namespace eval nsh1::nsh2 {test_ns_cmd_global}]
+} {{var in ::} {cmd in ::} {var in ::} {cmd in ::}}
+
+test namespace-5.6 {commands in different namespaces don't conflict} {
+    list [nsh1::test_ns_show] \
+         [nsh1::nsh2::test_ns_show]
+} {{::nsh1: 1} {::nsh1::nsh2: 2}}
+test namespace-5.7 {nested namespaces don't see variables in parent} {
+    set cmd {
+        namespace eval nsh1::nsh2 {set test_ns_var_hier1}
+    }
+    list [catch $cmd msg] $msg
+} {1 {can't read "test_ns_var_hier1": no such variable}}
+test namespace-5.8 {nested namespaces don't see commands in parent} {
+    set cmd {
+        namespace eval nsh1::nsh2 {test_ns_cmd_hier1}
+    }
+    list [catch $cmd msg] $msg
+} {1 {invalid command name "test_ns_cmd_hier1"}}
+
+test namespace-5.18 {usage for "namespace parent"} {
+    list [catch {namespace parent x y} msg] $msg
+} {1 {wrong # args: should be "namespace parent ?name?"}}
+
+test namespace-5.20 {querying namespace parent} {
+    list [namespace eval :: {namespace parent}] \
+        [namespace eval nsh1 {namespace parent}] \
+        [namespace eval nsh1::nsh2 {namespace parent}] \
+        [namespace eval nsh1::nsh2::nsh3a {namespace parent}] \
+} {{} :: ::nsh1 ::nsh1::nsh2}
+
+test namespace-5.21 {querying namespace parent for explicit namespace} {
+    list [namespace parent ::] \
+         [namespace parent nsh1] \
+         [namespace parent nsh1::nsh2] \
+         [namespace parent nsh1::nsh2::nsh3a]
+} {{} :: ::nsh1 ::nsh1::nsh2}
+
+# -----------------------------------------------------------------------
+# TEST: name resolution and caching
+# -----------------------------------------------------------------------
+test namespace-6.1 {relative ns names only looked up in current ns} {
+    namespace eval tns1 {}
+    namespace eval tns2 {}
+    namespace eval tns2::test_ns_cache3 {}
+    set trigger {
+        namespace eval tns2 {namespace current}
+    }
+    set trigger2 {
+        namespace eval tns2::test_ns_cache3 {namespace current}
+    }
+    list [namespace eval tns1 $trigger] \
+         [namespace eval tns1 $trigger2]
+} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
+test namespace-6.2 {relative ns names only looked up in current ns} {
+    namespace eval tns1::tns2 {}
+    list [namespace eval tns1 $trigger] \
+         [namespace eval tns1 $trigger2]
+} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
+test namespace-6.3 {relative ns names only looked up in current ns} {
+    namespace eval tns1::tns2::test_ns_cache3 {}
+    list [namespace eval tns1 $trigger] \
+         [namespace eval tns1 $trigger2]
+} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
+test namespace-6.4 {relative ns names only looked up in current ns} {
+    namespace delete tns1::tns2
+    list [namespace eval tns1 $trigger] \
+         [namespace eval tns1 $trigger2]
+} {::tns1::tns2 ::tns1::tns2::test_ns_cache3}
+
+test namespace-6.5 {define test commands} {
+    proc testcmd {} {
+        return "global version"
+    }
+    namespace eval tns1 {
+        proc trigger {} {
+            testcmd
+        }
+    }
+    tns1::trigger
+} {global version}
+
+test namespace-6.6 {one-level check for command shadowing} {
+    proc tns1::testcmd {} {
+        return "cache1 version"
+    }
+    tns1::trigger
+} {cache1 version}
+
+test namespace-6.7 {renaming commands changes command epoch} {
+    namespace eval tns1 {
+        rename testcmd testcmd_new
+    }
+    tns1::trigger
+} {global version}
+test namespace-6.8 {renaming back handles shadowing} {
+    namespace eval tns1 {
+        rename testcmd_new testcmd
+    }
+    tns1::trigger
+} {cache1 version}
+test namespace-6.9 {deleting commands changes command epoch} {
+    namespace eval tns1 {
+        rename testcmd ""
+    }
+    tns1::trigger
+} {global version}
+test namespace-6.10 {define test namespaces} {
+    namespace eval tns2 {
+        proc testcmd {} {
+            return "global cache2 version"
+        }
+    }
+    namespace eval tns1 {
+        proc trigger {} {
+            tns2::testcmd
+        }
+    }
+    namespace eval tns1::tns2 {
+        proc trigger {} {
+            testcmd
+        }
+    }
+    list [tns1::trigger] [tns1::tns2::trigger]
+} {{global cache2 version} {global version}}
+
+test namespace-6.11 {commands affect all parent namespaces} {
+    proc tns1::tns2::testcmd {} {
+        return "cache2 version"
+    }
+    list [tns1::trigger] [tns1::tns2::trigger]
+} {{cache2 version} {cache2 version}}
+
+# -----------------------------------------------------------------------
+# TEST: uplevel/upvar across namespace boundaries
+# -----------------------------------------------------------------------
+# Note that Tcl behaves a little differently for uplevel and upvar
+
+test namespace-7.1 {uplevel in namespace eval} jim {
+       set x 66
+    namespace eval uns1 {
+               variable y 55
+               set x 33
+        uplevel 1 set x
+    }
+} {66}
+
+test namespace-7.2 {upvar in ns proc} jim {
+       proc uns1::getvar {v} {
+               variable y
+               upvar $v var
+               list $var $y
+       }
+       uns1::getvar x
+} {66 55}
+
+# -----------------------------------------------------------------------
+# TEST: scoped values
+# -----------------------------------------------------------------------
+test namespace-10.1 {define namespace for scope test} {
+    namespace eval ins1 {
+        variable x "x-value"
+        proc show {args} {
+            return "show: $args"
+        }
+        proc do {args} {
+            return [eval $args]
+        }
+        list [set x] [show test]
+    }
+} {x-value {show: test}}
+
+test namespace-10.2 {command "namespace code" requires one argument} {
+    list [catch {namespace code} msg] $msg
+} {1 {wrong # args: should be "namespace code arg"}}
+
+test namespace-10.3 {command "namespace code" requires one argument} {
+    list [catch {namespace code first "second arg" third} msg] $msg
+} {1 {wrong # args: should be "namespace code arg"}}
+
+test namespace-10.4 {command "namespace code" gets current namesp context} {
+    namespace eval ins1 {
+        namespace code {"1 2 3" "4 5" 6}
+    }
+} {::namespace inscope ::ins1 {"1 2 3" "4 5" 6}}
+
+test namespace-10.5 {with one arg, first "scope" sticks} {
+    set sval [namespace eval ins1 {namespace code {one two}}]
+    namespace code $sval
+} {::namespace inscope ::ins1 {one two}}
+
+test namespace-10.6 {with many args, each "scope" adds new args} {
+    set sval [namespace eval ins1 {namespace code {one two}}]
+    namespace code "$sval three"
+} {::namespace inscope ::ins1 {one two} three}
+
+test namespace-10.7 {scoped commands work with eval} {
+    set cref [namespace eval ins1 {namespace code show}]
+    list [eval $cref "a" "b c" "d e f"]
+} {{show: a b c d e f}}
+
+test namespace-10.8 {scoped commands execute in namespace context} {
+    set cref [namespace eval ins1 {
+        namespace code {variable x; set x "some new value"}
+    }]
+    list [set ins1::x] [eval $cref] [set ins1::x]
+} {x-value {some new value} {some new value}}
+
+test namespace-11.1 {command caching} {
+       proc cmd1 {} { return global }
+       set result {}
+       namespace eval ns1 {
+               proc cmd1 {} { return ns1 }
+               proc cmd2 {} {
+                       uplevel 1 cmd1
+               }
+               lappend ::result [cmd2]
+       }
+       lappend result [ns1::cmd2]
+} {ns1 global}
+
+foreach cmd [info commands test_ns_*] {
+    rename $cmd ""
+}
+
+catch {rename cmd {}}
+catch {rename cmd1 {}}
+catch {rename cmd2 {}}
+catch {rename ncmd {}}
+catch {rename ncmd1 {}}
+catch {rename ncmd2 {}}
+catch {unset cref}
+catch {unset trigger}
+catch {unset trigger2}
+catch {unset sval}
+catch {unset msg}
+catch {unset x}
+catch {unset test_ns_var_global}
+catch {unset cmd}
+catch {eval namespace delete [namespace children :: test_ns_*]}
+
+# cleanup
+::tcltest::cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/jim/tests/parse.test b/jim/tests/parse.test
new file mode 100755 (executable)
index 0000000..8b03192
--- /dev/null
@@ -0,0 +1,338 @@
+source [file dirname [info script]]/testing.tcl
+
+test parse-1.1 "Quoted closing bracket" {
+       set x [string length "]"]
+} {1}
+
+test parse-1.2 "Quoted opening bracket" {
+       set x [string length "\["]
+} {1}
+
+test parse-1.3 "Quoted open brace" {
+       set x [string length "\{"]
+} {1}
+
+test parse-1.4 "Quoted open brace via var" {
+       set lb \{
+       set x [string length "$lb"]
+} {1}
+
+test parse-1.5 "Braced bracket" {
+       set x [string length {]}]
+} {1}
+
+test parse-1.6 "Dict sugar" -body {
+    unset -nocomplain a
+    array set a {a 1 b 2 c 3}
+    set x $a(
+} -returnCodes error -match glob -result "*"
+
+test parse-1.8 "Dict sugar" {
+    unset -nocomplain a
+    array set a {a 1 b 2 c 3}
+    set x $a([set y b])
+} 2
+
+test parse-1.9 "Backslash newline" {
+       set x 123;\
+       set y 456
+       list $x $y
+} {123 456}
+
+test parse-1.10 "Backslash newline in quotes" {
+       set x "abc\
+def"
+} "abc def"
+
+test parse-1.11 "Backslash newline in quotes after var" {
+       set y 1
+       set x "abc$y\
+def"
+} "abc1 def"
+
+test parse-1.12 "Backslash newline in quotes after var" {
+       set y 1
+       set x "abc$y\
+def"
+} "abc1 def"
+
+test parse-1.13 "Newline in quotes" {
+       set y 1
+       set x "abc
+def"
+} "abc\ndef"
+
+test parse-1.14 "Newline in quotes after var" {
+       set y 1
+       set x "abc$y
+def"
+} "abc1\ndef"
+
+test parse-1.15 "Space in quotes" {
+       set y 1
+       set x "abc def"
+} "abc def"
+
+test parse-1.16 "Space in quotes after var" {
+       set y 1
+       set x "abc${y} def"
+} "abc1 def"
+
+test parse-1.17 "Command and var in quotes" {
+       set y 1
+       set x "[set z 2][set y]"
+} 21
+
+test parse-1.18 "Command and var in bare context" {
+       set y 1
+       set x [set z 2][set y]
+} 21
+
+test parse-1.19 "Lone dollar sign in quotes" {
+       set y 1
+       set x "6$[set y]"
+} 6\$1
+
+test parse-1.20 "Command and var in bare context" {
+       set y 1
+       set x 6$[set y]
+} 6\$1
+
+test parse-1.21 "Comment" {
+       set y 1
+# A comment one a line
+       set x [set y] ;# comment after semicolon
+} 1
+
+test parse-1.22 "# char" {
+       set y 1
+       append y #
+       set x "[set y]#"
+} {1##}
+
+test parse-1.23 "newline in command" {
+       set y 1
+       set z 2
+       set x [incr y
+       incr z]
+       list $x $y $z
+} {3 2 3}
+
+test parse-1.24 "semicolon in command" {
+       set x [list a; list b c; list d e f]
+} {d e f}
+
+# Note that Tcl complains about the missing brace here
+# while Jim ignores it
+test parse-1.25 "missing brace in var" jim {
+       unset -nocomplain a
+       set a 3
+       set brace \{
+       set x [subst \$${brace}a]
+} 3
+
+test parse-1.26 "newline in braced var" {
+       set "a\nb" var1
+       set x ${a
+b}
+} var1
+
+test parse-1.27 "backslash escape in dict sugar" {
+       unset -nocomplain a
+       set a(b\x55d) 5
+       set x $a(b\x55d)
+} 5
+
+test parse-1.28 "nested dict sugar" {
+       unset -nocomplain a b
+       set a(V) 5
+       set b(5) five
+       set x $b($a(V))
+} five
+
+set dq {"}
+set script "set x ${dq}hello"
+
+test parse-1.29 "missing quote" -constraints jim -body {
+       eval $script
+} -returnCodes error -match glob -result {missing quote}
+
+test parse-1.30 "missing quote" {
+       info complete $script
+} 0
+
+test parse-1.31 "backslash newline in bare context" {
+       list abc\
+       123
+} {abc 123}
+
+test parse-1.32 "comment as last line of script" {
+       set script {set x 3; # this is a comment}
+       eval $script
+} 3
+
+test parse-1.33 "upper case hex escapes" {
+       list \x4A \x4F \x3C
+} {J O <}
+
+test parse-1.34 "octal escapes" {
+       list \112 \117 \074
+} {J O <}
+
+test parse-1.35 "invalid hex escape" {
+       list \xZZ
+} xZZ
+
+test parse-1.36 "unicode escape" jim {
+       list \u00b5
+} \xc2\xb5
+
+test parse-1.37 "invalid unicode escape after unicode" jim {
+       list \ub5x
+} \xc2\xb5x
+
+test parse-1.38 "invalid unicode escape" {
+       list \ux
+} ux
+
+test parse-1.39 "octal escape followed by invalid" {
+       list \76x
+} >x
+
+test parse-1.40 "list containing quoted trailing backslash" jim {
+       set x "abc \"def\\"
+       lindex $x 1
+} def\\
+
+test parse-1.41 "list containing quoted newline" {
+       set x {abc "def
+ghi"}
+       lindex $x 1
+} def\nghi
+
+test parse-1.42 "list containing missing quote" jim {
+       set x {abc "def}
+       lindex $x 1
+} def
+
+test parse-1.43 "list containing trailing backslash" {
+       set x "abc def\\"
+       lindex $x 1
+} def\\
+
+test parse-1.44 "list creation" {
+       list "a{ }d"
+} {{a{ }d}}
+
+test parse-1.45 "spaces before expr function args" {
+       expr {round  (3.2)}
+} 3
+
+test parse-1.46 "expr function missing paren" {
+       catch {expr {round 3.2}}
+} 1
+
+test parse-1.47 "backslash newline in quotes" {
+       # spaces
+       set x "abc\
+      def"
+} "abc def"
+
+test parse-1.48 "backslash newline in quotes" {
+       # tabs
+       set x "abc\
+               def"
+} "abc def"
+
+test parse-1.49 "backslash newline in quotes" {
+       # tabs plus newline
+       set x "abc\
+               
+def"
+} "abc \ndef"
+
+test parse-1.50 "backslash newline in quotes" {
+       # tabs plus newline
+       set x "abc\
+def"
+} "abc def"
+
+test parse-1.51 "special chars in dict sugar" {
+       unset -nocomplain a
+       set a(x$) 5
+       array names a
+} {{x$}}
+
+test parse-1.52 "special chars in dict sugar" {
+       set x $a(x$)
+} 5
+
+test parse-1.53 "special chars in dict sugar" {
+       unset -nocomplain a
+       set a(x\[) 5
+       array names a
+} {{x[}}
+
+test parse-1.54 "special chars in dict sugar" {
+       set x $a(x\[)
+} 5
+
+test parse-1.55 "special chars in dict sugar" {
+       unset -nocomplain a
+       set a(x\() 5
+       array names a
+} {x(}
+
+test parse-1.56 "special chars in dict sugar" {
+       set x $a(x\()
+} 5
+
+test parse-1.57 "special chars in dict sugar" {
+       unset -nocomplain a
+       set a(x() 5
+       array names a
+} {x(}
+
+test parse-1.58 "special chars in dict sugar" {
+       set x $a(x()
+} 5
+
+test parse-1.59 "special chars in dict sugar" {
+       unset -nocomplain a
+       set a(x") 5
+       lindex [array names a] 0
+} {x"}
+
+test parse-1.60 "special chars in dict sugar" {
+       set x $a(x")
+} 5
+
+test parse-1.61 "quote in command" {
+       set x [list \\" x]
+       lindex $x end
+} x
+
+test parse-1.62 "quoted orphan dollar sign" {
+       set x "x$"
+} {x$}
+
+test parse-1.63 "unquoted dollar sign" {
+       set x x$
+} {x$}
+
+test parse-1.64 "backslash in comment" {
+       set x 0
+       # comment \
+       incr x
+       incr x
+} 1
+
+test parse-1.65 "double backslash in comment" {
+       set x 0
+       # comment \\
+       incr x
+       incr x
+} 2
+
+
+testreport
diff --git a/jim/tests/perf.test b/jim/tests/perf.test
new file mode 100755 (executable)
index 0000000..145f432
--- /dev/null
@@ -0,0 +1,137 @@
+source [file dirname [info script]]/testing.tcl
+
+needs constraint manual
+
+set iterations 10000
+
+set version [info patchlevel]
+
+proc bench {name cmd} {
+       if {[catch {
+               set t [time $cmd 2]
+               set ms [format %.0f [expr {[lindex $t 0] / 1000}]]
+       }]} {
+               set ms ?
+       }
+       puts "$::version: $name ${ms}ms"
+}
+
+proc set_dict_sugar {} {
+       for {set i 0} {$i < $::iterations} {incr i} {
+               set a(b) $i
+       }
+}
+
+# Note that this case does not benefit from the dict sugar
+# speedup since a($b) needs to be interpolated and reparsed every time
+proc set_var_dict_sugar {} {
+       set b b
+       for {set i 0} {$i < $::iterations} {incr i} {
+               set a($b) $i
+       }
+}
+
+proc set_var_dict {} {
+       set b b
+       for {set i 0} {$i < $::iterations} {incr i} {
+               dict set a $b $i
+       }
+}
+
+proc read_file {file} {
+       set f [open $file]
+       while {[gets $f buf] >= 0} {
+       }
+       close $f
+}
+
+proc read_file_split {file} {
+       set f [open $file]
+       while {[gets $f buf] >= 0} {
+               split $buf \t
+       }
+       close $f
+}
+
+proc read_file_split_assign_foreach {file} {
+       set f [open $file]
+       while {[gets $f buf] >= 0} {
+               foreach {info(chan) info(datetime) info(duration) info(title) subtitle_genre info(desc) info(rating) dummy} [split $buf \t] {break}
+       }
+       close $f
+}
+
+proc read_file_split_assign_foreach_dict {file} {
+       set f [open $file]
+       while {[gets $f buf] >= 0} {
+               foreach {chan datetime duration title subtitle_genre desc rating dummy} [split $buf \t] {break}
+               dict set info chan $chan
+               dict set info duration $duration
+               dict set info title $title
+               dict set info subtitle_genre $subtitle_genre
+               dict set info desc $desc
+               dict set info rating $rating
+       }
+       close $f
+}
+
+proc read_file_split_assign_foreach_dictsugar {file} {
+       set f [open $file]
+       while {[gets $f buf] >= 0} {
+               foreach {chan datetime duration title subtitle_genre desc rating dummy} [split $buf \t] {break}
+               set info(chan) $chan
+               set info(duration) $duration
+               set info(title) $title
+               set info(subtitle_genre) $subtitle_genre
+               set info(desc) $desc
+               set info(rating) $rating
+       }
+       close $f
+}
+
+proc read_file_split_assign_foreach_simple {file} {
+       set f [open $file]
+       while {[gets $f buf] >= 0} {
+               foreach {chan datetime duration title subtitle_genre desc rating dummy} [split $buf \t] {break}
+       }
+       close $f
+}
+
+proc read_file_split_assign_lindex {file} {
+       set f [open $file]
+       while {[gets $f buf] >= 0} {
+               set split [split $buf \t]
+               set info(chan) [lindex $split 0]
+               set info(datetime) [lindex $split 1]
+               set info(duration) [lindex $split 2]
+               set info(title) [lindex $split 3]
+               set info(subtitle_genre) [lindex $split 4]
+               set info(desc) [lindex $split 5]
+               set info(rating) [lindex $split 6]
+       }
+       close $f
+}
+
+# Create a really big file
+set f [open test.in w]
+for {set i 0} {$i < $::iterations} {incr i} {
+       puts $f "a\tb\tc\te\tf\tg\th\ti\tj\tk"
+}
+close $f
+
+bench "set dictsugar" {set_dict_sugar}
+bench "set var dictsugar" {set_var_dict_sugar}
+bench "set var dict" {set_var_dict}
+# Read once before testing perf
+read_file test.in
+bench "read file" {read_file test.in}
+bench "read file split" {read_file_split test.in}
+bench "foreach: simple" {read_file_split_assign_foreach_simple test.in}
+bench "foreach: direct dictsugar" {read_file_split_assign_foreach test.in}
+bench "foreach: dict cmd" {read_file_split_assign_foreach_dict test.in}
+bench "foreach: assign to dictsugar" {read_file_split_assign_foreach_dictsugar test.in}
+bench "foreach: assign to dictsugar via lindex" {read_file_split_assign_lindex test.in}
+
+file delete test.in
+
+# testreport
diff --git a/jim/tests/pid.test b/jim/tests/pid.test
new file mode 100755 (executable)
index 0000000..6a534a5
--- /dev/null
@@ -0,0 +1,57 @@
+# Commands covered:  pid
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: pid.test,v 1.6 2000/04/10 17:19:03 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd pid posix
+needs cmd exec
+catch {package require regexp}
+testConstraint regexp [expr {[info commands regexp] ne {}}]
+testConstraint socket [expr {[info commands socket] ne {}}]
+testConstraint getpid [expr {[catch pid] == 0}]
+# This is a proxy for tcl || tclcompat
+testConstraint pidchan [expr {[info commands fconfigure] ne {}}]
+
+file delete test1
+
+test pid-1.1 {pid command} {regexp getpid} {
+    regexp {(^[0-9]+$)|(^0x[0-9a-fA-F]+$)} [pid]
+} 1
+test pid-1.2 {pid command} {regexp socket pidchan} {
+    set f [open {| echo foo | cat >test1} w]
+    set pids [pid $f]
+    close $f
+    catch {removeFile test1}
+    list [llength $pids] [regexp {^[0-9]+$} [lindex $pids 0]] \
+       [regexp {^[0-9]+$} [lindex $pids 1]] \
+       [expr {[lindex $pids 0] == [lindex $pids 1]}]
+} {2 1 1 0}
+test pid-1.3 {pid command} {socket pidchan} {
+    set f [open test1 w]
+    set pids [pid $f]
+    close $f
+    set pids
+} {}
+test pid-1.4 {pid command} pidchan {
+    list [catch {pid a b} msg] $msg
+} {1 {wrong # args: should be "pid ?channelId?"}}
+test pid-1.5 {pid command} pidchan {
+    list [catch {pid gorp} msg] $msg
+} {1 {can not find channel named "gorp"}}
+
+# cleanup
+file delete test1
+
+testreport
diff --git a/jim/tests/prefix.test b/jim/tests/prefix.test
new file mode 100755 (executable)
index 0000000..1540f75
--- /dev/null
@@ -0,0 +1,156 @@
+# Commands covered:  tcl::prefix
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd tcl::prefix prefix
+testConstraint namespace [expr {[info commands namespace] ne ""}]
+
+test string-26.1 {tcl::prefix, too few args} -body {
+    tcl::prefix match a
+} -returnCodes 1 -match glob -result {wrong # args: should be "tcl::prefix match ?options*? table string"}
+test string-26.2 {tcl::prefix, bad args} -body {
+    tcl::prefix match a b c
+} -returnCodes 1 -result {bad option "a": must be -error, -exact, or -message}
+test string-26.2.1 {tcl::prefix, empty table} -body {
+    tcl::prefix match {} foo
+} -returnCodes 1 -result {bad option "foo": no valid options}
+
+
+
+test string-26.3.1 {tcl::prefix, bad args} -body {
+    tcl::prefix match -error "x" -exact str1 str2
+} -returnCodes 1 -match glob -result *
+test string-26.3.2 {tcl::prefix, bad args} -body {
+    tcl::prefix match -error str1 str2
+} -returnCodes 1 -result {missing error options}
+test string-26.4 {tcl::prefix, bad args} -body {
+    tcl::prefix match -message str1 str2
+} -returnCodes 1 -result {missing message}
+test string-26.5 {tcl::prefix} {
+    tcl::prefix match {apa bepa cepa depa} cepa
+} cepa
+test string-26.6 {tcl::prefix} {
+    tcl::prefix match {apa bepa cepa depa} be
+} bepa
+test string-26.7 {tcl::prefix} -body {
+    tcl::prefix match -exact {apa bepa cepa depa} be
+} -returnCodes 1 -result {bad option "be": must be apa, bepa, cepa, or depa}
+test string-26.8 {tcl::prefix} -body {
+    tcl::prefix match -message switch {apa bear bepa depa} be
+} -returnCodes 1 -result {ambiguous switch "be": must be apa, bear, bepa, or depa}
+test string-26.9 {tcl::prefix} -body {
+    tcl::prefix match -error {} {apa bepa bear depa} be
+} -returnCodes 0 -result {}
+test string-26.10 {tcl::prefix} -body {
+    tcl::prefix match -error {-level 1} {apa bear bepa depa} be
+} -returnCodes 2 -result {ambiguous option "be": must be apa, bear, bepa, or depa}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test string-27.1 {tcl::prefix all, too few args} -body {
+    tcl::prefix all a
+} -returnCodes 1 -result {wrong # args: should be "tcl::prefix all table string"}
+test string-27.2 {tcl::prefix all, bad args} -body {
+    tcl::prefix all a b c
+} -returnCodes 1 -result {wrong # args: should be "tcl::prefix all table string"}
+
+
+
+test string-27.4 {tcl::prefix all} {
+    tcl::prefix all {apa bepa cepa depa} c
+} cepa
+test string-27.5 {tcl::prefix all} {
+    tcl::prefix all {apa bepa cepa depa} cepa
+} cepa
+test string-27.6 {tcl::prefix all} {
+    tcl::prefix all {apa bepa cepa depa} cepax
+} {}
+test string-27.7 {tcl::prefix all} {
+    tcl::prefix all {apa aska appa} a
+} {apa aska appa}
+test string-27.8 {tcl::prefix all} {
+    tcl::prefix all {apa aska appa} ap
+} {apa appa}
+test string-27.9 {tcl::prefix all} {
+    tcl::prefix all {apa aska appa} p
+} {}
+test string-27.10 {tcl::prefix all} {
+    tcl::prefix all {apa aska appa} {}
+} {apa aska appa}
+
+test string-28.1 {tcl::prefix longest, too few args} -body {
+    tcl::prefix longest a
+} -returnCodes 1 -result {wrong # args: should be "tcl::prefix longest table string"}
+test string-28.2 {tcl::prefix longest, bad args} -body {
+    tcl::prefix longest a b c
+} -returnCodes 1 -result {wrong # args: should be "tcl::prefix longest table string"}
+
+
+
+test string-28.4 {tcl::prefix longest} {
+    tcl::prefix longest {apa bepa cepa depa} c
+} cepa
+test string-28.5 {tcl::prefix longest} {
+    tcl::prefix longest {apa bepa cepa depa} cepa
+} cepa
+test string-28.6 {tcl::prefix longest} {
+    tcl::prefix longest {apa bepa cepa depa} cepax
+} {}
+test string-28.7 {tcl::prefix longest} {
+    tcl::prefix longest {apa aska appa} a
+} a
+test string-28.8 {tcl::prefix longest} {
+    tcl::prefix longest {apa aska appa} ap
+} ap
+test string-28.9 {tcl::prefix longest} {
+    tcl::prefix longest {apa bska appa} a
+} ap
+test string-28.10 {tcl::prefix longest} {
+    tcl::prefix longest {apa bska appa} {}
+} {}
+test string-28.11 {tcl::prefix longest} {
+    tcl::prefix longest {{} bska appa} {}
+} {}
+test string-28.12 {tcl::prefix longest} {
+    tcl::prefix longest {apa {} appa} {}
+} {}
+test string-28.13 {tcl::prefix longest} {
+    # Test UTF8 handling
+    tcl::prefix longest {ax\x90 bep ax\x91} a
+} ax
+
+test string-29.1 {tcl::prefix from another namespace} namespace {
+    namespace eval abc {
+        tcl::prefix longest {apa bepa cepa depa} cepa
+    }
+} cepa
+
+testreport
diff --git a/jim/tests/proc-new.test b/jim/tests/proc-new.test
new file mode 100755 (executable)
index 0000000..8703748
--- /dev/null
@@ -0,0 +1,127 @@
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+needs cmd array
+
+proc aproc {} {
+       list
+}
+proc bproc {b} {
+       list b $b
+}
+proc cproc {b c} {
+       list b $b c $c
+}
+proc dproc {b c {d dd}} {
+       list b $b c $c d $d
+}
+proc eproc {b c {d dd} e} {
+       list b $b c $c d $d e $e
+}
+proc fproc {b c {d dd} args} {
+       list b $b c $c d $d args $args
+}
+proc gproc {b c {d dd} args e} {
+       list b $b c $c d $d args $args e $e
+}
+proc hproc {{a aa} args} {
+       list a $a args $args
+}
+
+proc iproc {{a aa} b {c cc}} {
+       list a $a b $b c $c
+}
+
+proc jproc {args {a aa} b {c cc} d} {
+       list a $a b $b c $c d $d args $args
+}
+
+set n 1
+foreach {proc params result} {
+       aproc {} {}
+       bproc B {b B}
+       cproc {B C} {b B c C}
+       dproc {B C} {b B c C d dd}
+       dproc {B C D} {b B c C d D}
+       eproc {B C D E} {b B c C d D e E}
+       eproc {B C E} {b B c C d dd e E}
+       fproc {B C} {b B c C d dd args {}}
+       fproc {B C D} {b B c C d D args {}}
+       fproc {B C D E} {b B c C d D args E}
+       fproc {B C D E F} {b B c C d D args {E F}}
+       gproc {B C E} {b B c C d dd args {} e E}
+       gproc {B C D E} {b B c C d D args {} e E}
+       gproc {B C D X E} {b B c C d D args X e E}
+       gproc {B C D X Y Z E} {b B c C d D args {X Y Z} e E}
+       hproc {} {a aa args {}}
+       hproc {A} {a A args {}}
+       hproc {A X Y Z} {a A args {X Y Z}}
+       iproc {B} {a aa b B c cc}
+       iproc {A B} {a A b B c cc}
+       iproc {A B C} {a A b B c C}
+       jproc {B D} {a aa b B c cc d D args {}}
+       jproc {A B D} {a A b B c cc d D args {}}
+       jproc {A B C D} {a A b B c C d D args {}}
+       jproc {E F A B C D} {a A b B c C d D args {E F}}
+} {
+       test proc-1.$n "Proc args combos" [list $proc {*}$params] $result
+       incr n
+}
+
+proc onearg_search {{nocase ""} value list} {
+       lsearch {*}$nocase $list $value
+}
+
+proc multiarg_search {args value list} {
+       lsearch {*}$args $list $value
+}
+
+test proc-2.1 "Real test of optional switches" {
+       onearg_search c {A a B b C c D d}
+} 5
+
+test proc-2.2 "Real test of optional switches" {
+       onearg_search -nocase c {A a B b C c D d}
+} 4
+
+test proc-2.3 "Real test of optional switches" {
+       multiarg_search -glob c* {A a B b C c D d}
+} 5
+
+test proc-2.4 "Real test of optional switches" {
+       multiarg_search -nocase -glob c* {A a B b C c D d}
+} 4
+
+test proc-3.1 "Rename optional args" {
+       proc a {b {args vars}} {
+       }
+       catch {a} msg
+       set msg
+} {wrong # args: should be "a b ?vars ...?"}
+
+test proc-3.2 "Rename optional args" {
+       proc a {b {args vars} c} {
+       }
+       catch {a} msg
+       set msg
+} {wrong # args: should be "a b ?vars ...? c"}
+
+test proc-3.2 "Rename optional args" {
+       proc a {b {args vars}} {
+               return $vars
+       }
+       a B C D
+} {C D}
+
+test proc-3.3 "dict sugar arg" {
+       proc a {b(c)} { return $b}
+       a 4
+} {c 4}
+
+test proc-3.4 "invalid upref in rightargs" {
+       proc a {{x 2} &b} { return $b}
+       unset -nocomplain B
+       catch {a B}
+} 1
+
+testreport
diff --git a/jim/tests/proc.test b/jim/tests/proc.test
new file mode 100755 (executable)
index 0000000..50c9674
--- /dev/null
@@ -0,0 +1,380 @@
+# Commands covered:  proc, return, global
+#
+# This file, proc-old.test, includes the original set of tests for Tcl's
+# proc, return, and global commands. There is now a new file proc.test
+# that contains tests for the tclProc.c source file.
+#
+# Sourcing this file into Tcl runs the tests and generates output for
+# errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: proc-old.test,v 1.6 2000/04/10 17:19:03 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+needs cmd array
+
+catch {rename t1 ""}
+catch {rename foo ""}
+
+proc tproc {} {return a; return b}
+test proc-old-1.1 {simple procedure call and return} {tproc} a
+proc tproc x {
+    set x [expr $x+1]
+    return $x
+}
+test proc-old-1.2 {simple procedure call and return} {tproc 2} 3
+test proc-old-1.3 {simple procedure call and return} {
+    proc tproc {} {return foo}
+} {tproc}
+test proc-old-1.4 {simple procedure call and return} {
+    proc tproc {} {return}
+    tproc
+} {}
+proc tproc1 {a}   {incr a; return $a}
+proc tproc2 {a b} {incr a; return $a}
+test proc-old-1.5 {simple procedure call and return (2 procs with same body but different parameters)} {
+    list [tproc1 123] [tproc2 456 789]
+} {124 457}
+test proc-old-1.6 {simple procedure call and return (shared proc body string)} {
+    set x {}
+    proc tproc {} {}   ;# body is shared with x
+    list [tproc] [append x foo]
+} {{} foo}
+
+test proc-old-2.1 {local and global variables} {
+    proc tproc x {
+       set x [expr $x+1]
+       return $x
+    }
+    set x 42
+    list [tproc 6] $x
+} {7 42}
+test proc-old-2.2 {local and global variables} {
+    proc tproc x {
+       set y [expr $x+1]
+       return $y
+    }
+    set y 18
+    list [tproc 6] $y
+} {7 18}
+test proc-old-2.3 {local and global variables} {
+    proc tproc x {
+       global y
+       set y [expr $x+1]
+       return $y
+    }
+    set y 189
+    list [tproc 6] $y
+} {7 7}
+test proc-old-2.4 {local and global variables} {
+    proc tproc x {
+       global y
+       return [expr $x+$y]
+    }
+    set y 189
+    list [tproc 6] $y
+} {195 189}
+catch {unset _undefined_}
+test proc-old-2.5 {local and global variables} {
+    proc tproc x {
+       global _undefined_
+       return $_undefined_
+    }
+    list [catch {tproc xxx} msg] $msg
+} {1 {can't read "_undefined_": no such variable}}
+test proc-old-2.6 {local and global variables} {
+    set a 114
+    set b 115
+    global a b
+    list $a $b
+} {114 115}
+
+proc do {cmd} {eval $cmd}
+test proc-old-3.1 {local and global arrays} {
+    catch {unset a}
+    set a(0) 22
+    list [catch {do {global a; set a(0)}} msg] $msg
+} {0 22}
+test proc-old-3.2 {local and global arrays} {
+    catch {unset a}
+    set a(x) 22
+    list [catch {do {global a; set a(x) newValue}} msg] $msg $a(x)
+} {0 newValue newValue}
+test proc-old-3.3 {local and global arrays} {
+    catch {unset a}
+    set a(x) 22
+    set a(y) 33
+    list [catch {do {global a; unset a(y)}; array names a} msg] $msg
+} {0 x}
+test proc-old-3.4 {local and global arrays} {
+    catch {unset a}
+    set a(x) 22
+    set a(y) 33
+    list [catch {do {global a; unset a; info exists a}} msg] $msg \
+           [info exists a]
+} {0 0 0}
+test proc-old-3.5 {local and global arrays} {
+    catch {unset a}
+    set a(x) 22
+    set a(y) 33
+    list [catch {do {global a; unset a(y); array names a}} msg] $msg
+} {0 x}
+catch {unset a}
+test proc-old-3.6 {local and global arrays} {
+    catch {unset a}
+    set a(x) 22
+    set a(y) 33
+    do {global a; do {global a; unset a}; set a(z) 22}
+    list [catch {array names a} msg] $msg
+} {0 z}
+test proc-old-3.1 {arguments and defaults} {
+    proc tproc {x y z} {
+       return [list $x $y $z]
+    }
+    tproc 11 12 13
+} {11 12 13}
+test proc-old-3.2 {arguments and defaults} {
+    proc tproc {x y z} {
+       return [list $x $y $z]
+    }
+    list [catch {tproc 11 12} msg]
+} {1}
+test proc-old-3.3 {arguments and defaults} {
+    proc tproc {x y z} {
+       return [list $x $y $z]
+    }
+    list [catch {tproc 11 12 13 14} msg]
+} {1}
+test proc-old-3.4 {arguments and defaults} {
+    proc tproc {x {y y-default} {z z-default}} {
+       return [list $x $y $z]
+    }
+    tproc 11 12 13
+} {11 12 13}
+test proc-old-3.5 {arguments and defaults} {
+    proc tproc {x {y y-default} {z z-default}} {
+       return [list $x $y $z]
+    }
+    tproc 11 12
+} {11 12 z-default}
+test proc-old-3.6 {arguments and defaults} {
+    proc tproc {x {y y-default} {z z-default}} {
+       return [list $x $y $z]
+    }
+    tproc 11
+} {11 y-default z-default}
+test proc-old-3.7 {arguments and defaults} {
+    proc tproc {x {y y-default} {z z-default}} {
+       return [list $x $y $z]
+    }
+    list [catch {tproc} msg]
+} {1}
+# Note: This requires new TIP #288 support
+test proc-old-3.8 {arguments and defaults} {
+    list [catch {
+       proc tproc {x {y y-default} z} {
+           return [list $x $y $z]
+       }
+       tproc 2 3
+    } msg] $msg
+} {0 {2 y-default 3}}
+test proc-old-3.9 {arguments and defaults} {
+    proc tproc {x {y y-default} args} {
+       return [list $x $y $args]
+    }
+    tproc 2 3 4 5
+} {2 3 {4 5}}
+test proc-old-3.10 {arguments and defaults} {
+    proc tproc {x {y y-default} args} {
+       return [list $x $y $args]
+    }
+    tproc 2 3
+} {2 3 {}}
+test proc-old-3.11 {arguments and defaults} {
+    proc tproc {x {y y-default} args} {
+       return [list $x $y $args]
+    }
+    tproc 2
+} {2 y-default {}}
+test proc-old-3.12 {arguments and defaults} {
+    proc tproc {x {y y-default} args} {
+       return [list $x $y $args]
+    }
+    list [catch {tproc} msg]
+} {1}
+
+test proc-old-4.1 {variable numbers of arguments} {
+    proc tproc args {return $args}
+    tproc
+} {}
+test proc-old-4.2 {variable numbers of arguments} {
+    proc tproc args {return $args}
+    tproc 1 2 3 4 5 6 7 8
+} {1 2 3 4 5 6 7 8}
+test proc-old-4.3 {variable numbers of arguments} {
+    proc tproc args {return $args}
+    tproc 1 {2 3} {4 {5 6} {{{7}}}} 8
+} {1 {2 3} {4 {5 6} {{{7}}}} 8}
+test proc-old-4.4 {variable numbers of arguments} {
+    proc tproc {x y args} {return $args}
+    tproc 1 2 3 4 5 6 7
+} {3 4 5 6 7}
+test proc-old-4.5 {variable numbers of arguments} {
+    proc tproc {x y args} {return $args}
+    tproc 1 2
+} {}
+test proc-old-4.6 {variable numbers of arguments} {
+    proc tproc {x missing args} {return $args}
+    list [catch {tproc 1} msg]
+} {1}
+
+test proc-old-5.1 {error conditions} {
+    list [catch {proc} msg]
+} {1}
+test proc-old-5.2 {error conditions} {
+    list [catch {proc tproc b} msg]
+} {1}
+test proc-old-5.3 {error conditions} {
+    list [catch {proc tproc b c d e} msg]
+} {1}
+
+
+
+test proc-old-5.6 {error conditions} {
+    list [catch {proc tproc {{} y} {return foo}} msg] $msg
+} {1 {argument with no name}}
+test proc-old-5.7 {error conditions} {
+    list [catch {proc tproc {{x 1 2} y} {return foo}} msg] $msg
+} {1 {too many fields in argument specifier "x 1 2"}}
+test proc-old-5.8 {error conditions} {
+    catch {return}
+} 2
+test proc-old-5.9 {error conditions} {
+    list [catch {global} msg] $msg
+} {1 {wrong # args: should be "global varName ?varName ...?"}}
+proc tproc {} {
+    set a 22
+    global a
+}
+test proc-old-5.10 {error conditions} {
+    list [catch {tproc} msg] $msg
+} {1 {variable "a" already exists}}
+test proc-old-5.11 {error conditions} {
+    catch {rename tproc {}}
+    catch {
+       proc tproc {x {} z} {return foo}
+    }
+    list [catch {tproc 1} msg] $msg
+} {1 {invalid command name "tproc"}}
+test proc-old-5.12 {error conditions} {
+    proc tproc {} {
+       set a 22
+       error "error in procedure"
+       return
+    }
+    list [catch tproc msg] $msg
+} {1 {error in procedure}}
+
+# The tests below will really only be useful when run under Purify or
+# some other system that can detect accesses to freed memory...
+
+test proc-old-6.1 {procedure that redefines itself} {
+    proc tproc {} {
+       proc tproc {} {
+           return 44
+       }
+       return 45
+    }
+    tproc
+} 45
+test proc-old-6.2 {procedure that deletes itself} {
+    proc tproc {} {
+       rename tproc {}
+       return 45
+    }
+    tproc
+} 45
+
+proc tproc code {
+    return -code $code abc
+}
+test proc-old-7.1 {return with special completion code} {
+    list [catch {tproc ok} msg] $msg
+} {0 abc}
+test proc-old-7.2 {return with special completion code} {
+    list [catch {tproc error} msg] $msg
+} {1 abc}
+test proc-old-7.3 {return with special completion code} {
+    list [catch {tproc return} msg] $msg
+} {2 abc}
+test proc-old-7.4 {return with special completion code} {
+    list [catch {tproc break} msg] $msg
+} {3 abc}
+test proc-old-7.5 {return with special completion code} {
+    list [catch {tproc continue} msg] $msg
+} {4 abc}
+test proc-old-7.6 {return with special completion code} {
+    list [catch {tproc -14} msg] $msg
+} {-14 abc}
+test proc-old-7.7 {return with special completion code} {
+    list [catch {tproc gorp} msg]
+} {1}
+test proc-old-7.8 {return with special completion code} {
+    list [catch {tproc 10b} msg]
+} {1}
+test proc-old-7.9 {return with special completion code} {
+    proc tproc2 {} {
+       tproc return
+    }
+    list [catch tproc2 msg] $msg
+} {0 abc}
+test proc-old-7.10 {return with special completion code} {
+    proc tproc2 {} {
+       return -code error
+    }
+    list [catch tproc2 msg] $msg
+} {1 {}}
+
+test proc-old-8.1 {unset and undefined local arrays} {
+    proc t1 {} {
+        foreach v {xxx, yyy} {
+            catch {unset $v}
+        }
+        set yyy(foo) bar
+    }
+    t1
+} bar
+
+test proc-old-9.1 {empty command name} {
+    catch {rename {} ""}
+    proc t1 {args} {
+        return
+    }
+    set v [t1]
+    catch {$v}
+} 1
+
+test proc-old-10.1 {ByteCode epoch change during recursive proc execution} {
+    proc t1 x {
+        set y 20
+        rename expr expr.old
+        rename expr.old expr
+        if $x then {t1 0} ;# recursive call after foo's code is invalidated
+        return 20
+    }
+    t1 1
+} 20
+
+# cleanup
+catch {rename t1 ""}
+catch {rename foo ""}
+
+testreport
diff --git a/jim/tests/procref.test b/jim/tests/procref.test
new file mode 100755 (executable)
index 0000000..a9fdf41
--- /dev/null
@@ -0,0 +1,56 @@
+# Tests auto-upref with the "&name" syntax
+
+source [file dirname [info script]]/testing.tcl
+
+needs constraint jim
+
+proc a1 {&b c} {
+       append b b
+       append c c
+}
+
+proc a2 {&b {dummy 3} &c} {
+       append b b
+       append c c
+}
+
+proc a3 {&b(c)} {
+       append b(c) b_c
+}
+
+# This is treated as a normal var "&b"
+proc a4 {{&b x}} {
+       append &b B
+}
+
+set B 1
+set C 1
+
+test procref-1.1 {Basic test} {
+       a1 B $C
+       set B
+} {1b}
+
+test procref-1.2 {Basic test} {
+       a1 B $C
+       set B
+} {1bb}
+
+test procref-1.3 {Unset var} -body {
+       a1 unsetB $C
+} -returnCodes error -result {can't read "unsetB": no such variable}
+
+test procref-1.4 {Left and right args are refs} {
+       a2 B C
+       list $B $C
+} {1bbb 1c}
+
+test procref-1.5 {Invalid arg} -body {
+       a3 B
+} -returnCodes error -result {bad variable name "b(c)": upvar won't create a scalar variable that looks like an array element}
+
+test procref-1.6 {Default arg as ref} {
+       a4
+} xB
+
+testreport
diff --git a/jim/tests/regcount.test b/jim/tests/regcount.test
new file mode 100755 (executable)
index 0000000..96f4ddd
--- /dev/null
@@ -0,0 +1,112 @@
+source [file dirname [info script]]/testing.tcl
+
+needs cmd regexp
+testConstraint regexp_are [expr {[regexp {\d} 1]}]
+needs constraint regexp_are
+
+# Test regexp counted repetitions
+
+set n 0
+foreach {pat str exp} {
+       a+ bac a
+       a{1,} bac a
+       a* bac {{}}
+       a{0,} bac {{}}
+       aa+ bac {}
+       a{2,} bac {}
+       a{2,} bacaad aa
+       a{3,} bacaad {}
+       {a{2,}$} bacaad {}
+       {a{2,}$} bacaa aa
+       {a{2,}$} ba {}
+       {a{2,}$} aa aa
+       {a{0,0}b$} b b
+       {a{1,1}b$} b {}
+       {a{1,1}b$} cab ab
+       {a{2,2}b$} cab {}
+       {a{2,2}b$} cabaabx {}
+       {a{2,2}b$} cacaab aab
+       ca{2,4}b cacaab caab
+       ca{2,3}b cacaab caab
+       ca{2,3}b cacaaab caaab
+       c(a|b){2,3}d xcbad {cbad a}
+       c(a|b){2,3}d xcabbd {cabbd b}
+       c(a|b){2,3}d xcbaaad {}
+       a{4} baaaad aaaa
+       a{2,5} baaaad aaaa
+       a{1,3} baaaad aaa
+       a{1,2} baaaad aa
+       a{3,4} baaaad aaaa
+       a{5,6} baaaad {}
+       a{4}? baaaad aaaa
+       a{2,5}? baaaad aa
+       a{1,3}? baaaad a
+       a{1,2}? baaaad a
+       a{3,4}? baaaad aaa
+       a{5,6}? baaaad {}
+       {\d{1,3}} 239 239
+       (aa|bb)?c xabbaac {aac aa}
+       (a|y)+ bac {a a}
+       (a|y){1,} bac {a a}
+       (a|y)* bac {{} {}}
+       (a|y){0,} bac {{} {}}
+       (a|y)a+ bac {}
+       (a|y){2,} bac {}
+       (a|y){2,} bacaad {aa a}
+       (a|y){3,} bacaad {}
+       {(a|y){2,}$} bacaad {}
+       {(a|y){2,}$} bacaa {aa a}
+       {(a|y){2,}$} ba {}
+       {(a|y){2,}$} aa {aa a}
+       {(a|y){0,0}b$} b {b {}}
+       {(a|y){1,1}b$} b {}
+       {(a|y){1,1}b$} cab {ab a}
+       {(a|y){2,2}b$} cab {}
+       {(a|y){2,2}b$} cabaabx {}
+       {(a|y){2,2}b$} cacaab {aab a}
+       c(a|y){2,4}b cacaab {caab a}
+       c(a|y){2,3}b cacaab {caab a}
+       c(a|y){2,3}b cacaaab {caaab a}
+       c((a|y)|b){2,3}d xcbad {cbad a a}
+       ####c((a|y)|b){2,3}d xcabbd {cabbd b {}}
+       c((a|y)|b){2,3}d xcbaaad {}
+       (a|y){4} baaaad {aaaa a}
+       (a|y){2,5} baaaad {aaaa a}
+       (a|y){1,3} baaaad {aaa a}
+       (a|y){1,2} baaaad {aa a}
+       (a|y){3,4} baaaad {aaaa a}
+       (a|y){5,6} baaaad {}
+       (a|y){4}? baaaad {aaaa a}
+       (a|y){2,5}? baaaad {aa a}
+       (a|y){1,3}? baaaad {a a}
+       (a|y){1,2}? baaaad {a a}
+       (a|y){3,4}? baaaad {aaa a}
+       (a|y){5,6}? baaaad {}
+    {[[:alpha:]]+} _bcd56_ef bcd
+    {[[:alnum:]]+} _bcd56_ef bcd56
+    {[[:space:]]+} "_bc \t\r\n\f\v_" "{ \t\r\n\f\v}"
+    {[\x41-\x43]+} "_ABCD_" ABC
+    {\m.+\M} "#A test#" "{A test}"
+    {\m.+?\M} "#A test#" "A"
+    {\m\M} "a" ""
+    {ab*c} xnbbmbbbc {}
+    {.^xxx} yyy {}
+    {\mb} "   abc   " ""
+       ####((a*)*b)*b aaaaaaaaaaaaaaaaaaaaaaaaab {b {} {}}
+       ####(a*)* aab {aa {}}
+       {^([^:=]*)(:)?(=)?$} version {version version {} {}}
+} {
+       if {[string match #* $pat]} {
+               continue
+       }
+       #puts \t[list $pat $str [regexp -inline -- $pat $str]]
+       test regcount-1.[incr n] "Test: regexp $pat $str" [list regexp -inline -- $pat $str] $exp
+}
+
+test regcount-2.1 "regexp counts cleared" {
+       set re "((a|b){1,2}(c{2,3}))"
+       regexp -inline $re xabcccce
+       regexp -inline $re xabcccce
+} {abccc abccc b ccc}
+
+testreport
diff --git a/jim/tests/regexp.test b/jim/tests/regexp.test
new file mode 100755 (executable)
index 0000000..7fa3ee0
--- /dev/null
@@ -0,0 +1,679 @@
+# Commands covered:  regexp, regsub
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: regexp.test,v 1.30.2.1 2008/08/21 23:19:06 hobbs Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd regexp
+
+catch {unset foo}
+test regexp-1.1 {basic regexp operation} {
+    regexp ab*c abbbc
+} 1
+test regexp-1.2 {basic regexp operation} {
+    regexp ab*c ac
+} 1
+test regexp-1.3 {basic regexp operation} {
+    regexp ab*c ab
+} 0
+test regexp-1.4 {basic regexp operation} {
+    regexp -- -gorp abc-gorpxxx
+} 1
+test regexp-1.5 {basic regexp operation} {
+    regexp {^([^ ]*)[ ]*([^ ]*)} "" a
+} 1
+#test regexp-1.6 {basic regexp operation} {
+#    list [catch {regexp {} abc} msg] $msg
+#} {0 1}
+#test regexp-1.7 {regexp utf compliance} {
+#    # if not UTF-8 aware, result is "0 1"
+#    set foo "\u4e4eb q"
+#    regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar
+#    list [string compare $foo $bar] [regexp 4 $bar]
+#} {0 0}
+
+
+test regexp-2.1 {getting substrings back from regexp} {
+    set foo {}
+    list [regexp ab*c abbbbc foo] $foo
+} {1 abbbbc}
+test regexp-2.2 {getting substrings back from regexp} {
+    set foo {}
+    set f2 {}
+    list [regexp a(b*)c abbbbc foo f2] $foo $f2
+} {1 abbbbc bbbb}
+test regexp-2.3 {getting substrings back from regexp} {
+    set foo {}
+    set f2 {}
+    list [regexp a(b*)(c) abbbbc foo f2] $foo $f2
+} {1 abbbbc bbbb}
+test regexp-2.4 {getting substrings back from regexp} {
+    set foo {}
+    set f2 {}
+    set f3 {}
+    list [regexp a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3
+} {1 abbbbc bbbb c}
+test regexp-2.5 {getting substrings back from regexp} {
+    set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {};
+    set f6 {}; set f7 {}; set f8 {}; set f9 {}; set fa {}; set fb {};
+    list [regexp (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*)(a*)(b*) \
+             12223345556789999aabbb \
+           foo f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb] $foo $f1 $f2 $f3 $f4 $f5 \
+           $f6 $f7 $f8 $f9 $fa $fb
+} {1 12223345556789999aabbb 1 222 33 4 555 6 7 8 9999 aa bbb}
+test regexp-2.6 {getting substrings back from regexp} {
+    set foo 2; set f2 2; set f3 2; set f4 2
+    list [regexp (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4
+} {1 a a {} {}}
+test regexp-2.7 {getting substrings back from regexp} {
+    set foo 1; set f2 1; set f3 1; set f4 1
+    list [regexp (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4
+} {1 ac a {} c}
+test regexp-2.8 {getting substrings back from regexp} {
+    set match {}
+    list [regexp {^a*b} aaaab match] $match
+} {1 aaaab}
+test regexp-2.9 {getting substrings back from regexp} {
+    set foo {}
+    set f2 {}
+    list [regexp f\352te(b*)c f\352tebbbbc foo f2] $foo $f2
+} [list 1 f\352tebbbbc bbbb]
+test regexp-2.10 {getting substrings back from regexp} {
+    set foo {}
+    set f2 {}
+    list [regexp f\352te(b*)c eff\352tebbbbc foo f2] $foo $f2
+} [list 1 f\352tebbbbc bbbb]
+
+test regexp-3.1 {-indices option to regexp} {
+    set foo {}
+    list [regexp -indices ab*c abbbbc foo] $foo
+} {1 {0 5}}
+test regexp-3.2 {-indices option to regexp} {
+    set foo {}
+    set f2 {}
+    list [regexp -indices a(b*)c abbbbc foo f2] $foo $f2
+} {1 {0 5} {1 4}}
+test regexp-3.3 {-indices option to regexp} {
+    set foo {}
+    set f2 {}
+    list [regexp -indices a(b*)(c) abbbbc foo f2] $foo $f2
+} {1 {0 5} {1 4}}
+test regexp-3.4 {-indices option to regexp} {
+    set foo {}
+    set f2 {}
+    set f3 {}
+    list [regexp -indices a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3
+} {1 {0 5} {1 4} {5 5}}
+test regexp-3.5 {-indices option to regexp} {
+    set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {};
+    set f6 {}; set f7 {}; set f8 {}; set f9 {}
+    list [regexp -indices (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*) \
+           12223345556789999 \
+           foo f1 f2 f3 f4 f5 f6 f7 f8 f9] $foo $f1 $f2 $f3 $f4 $f5 \
+           $f6 $f7 $f8 $f9
+} {1 {0 16} {0 0} {1 3} {4 5} {6 6} {7 9} {10 10} {11 11} {12 12} {13 16}}
+test regexp-3.6 {getting substrings back from regexp} {
+    set foo 2; set f2 2; set f3 2; set f4 2
+    list [regexp -indices (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4
+} {1 {1 1} {1 1} {-1 -1} {-1 -1}}
+test regexp-3.7 {getting substrings back from regexp} {
+    set foo 1; set f2 1; set f3 1; set f4 1
+    list [regexp -indices (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4
+} {1 {1 2} {1 1} {-1 -1} {2 2}}
+
+test regexp-4.1 {-nocase option to regexp} {
+    regexp -nocase foo abcFOo
+} 1
+test regexp-4.2 {-nocase option to regexp} {
+    set f1 22
+    set f2 33
+    set f3 44
+    list [regexp -nocase {a(b*)([xy]*)z} aBbbxYXxxZ22 f1 f2 f3] $f1 $f2 $f3
+} {1 aBbbxYXxxZ Bbb xYXxx}
+test regexp-4.3 {-nocase option to regexp} {
+    regexp -nocase FOo abcFOo
+} 1
+set x abcdefghijklmnopqrstuvwxyz1234567890
+set x $x$x$x$x$x$x$x$x$x$x$x$x
+test regexp-4.4 {case conversion in regexp} {
+    list [regexp -nocase $x $x foo] $foo
+} "1 $x"
+catch {unset x}
+
+test regexp-5.1 {exercise cache of compiled expressions} {
+    regexp .*a b
+    regexp .*b c
+    regexp .*c d
+    regexp .*d e
+    regexp .*e f
+    regexp .*a bbba
+} 1
+test regexp-5.2 {exercise cache of compiled expressions} {
+    regexp .*a b
+    regexp .*b c
+    regexp .*c d
+    regexp .*d e
+    regexp .*e f
+    regexp .*b xxxb
+} 1
+test regexp-5.3 {exercise cache of compiled expressions} {
+    regexp .*a b
+    regexp .*b c
+    regexp .*c d
+    regexp .*d e
+    regexp .*e f
+    regexp .*c yyyc
+} 1
+test regexp-5.4 {exercise cache of compiled expressions} {
+    regexp .*a b
+    regexp .*b c
+    regexp .*c d
+    regexp .*d e
+    regexp .*e f
+    regexp .*d 1d
+} 1
+test regexp-5.5 {exercise cache of compiled expressions} {
+    regexp .*a b
+    regexp .*b c
+    regexp .*c d
+    regexp .*d e
+    regexp .*e f
+    regexp .*e xe
+} 1
+
+test regexp-6.1 {regexp errors} jim {
+    list [catch {regexp a} msg] $msg
+} {1 {wrong # args: should be "regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"}}
+test regexp-6.2 {regexp errors} jim {
+    list [catch {regexp -nocase a} msg] $msg
+} {1 {wrong # args: should be "regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"}}
+test regexp-6.3 {regexp errors} jim {
+    list [catch {regexp -gorp a} msg] $msg
+} {1 {bad switch "-gorp": must be --, -all, -indices, -inline, -line, -nocase, or -start}}
+test regexp-6.4 {regexp errors} {
+    catch {regexp a( b} msg
+} 1
+#test regexp-6.5 {regexp errors} {
+#    list [catch {regexp a) b} msg] [string match *parentheses* $msg]
+#} {1 1}
+test regexp-6.6 {regexp errors} {
+    list [catch {regexp a a f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1} msg] $msg
+} {0 1}
+test regexp-6.7 {regexp errors} {
+    list [catch {regexp (x)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) xyzzy} msg] $msg
+} {0 0}
+test regexp-6.8 {regexp errors} jim {
+    catch {unset f1}
+    set f1 44
+    list [catch {regexp abc abc f1(f2)} msg] $msg
+} {1 {can't set "f1(f2)": variable isn't array}}
+test regexp-6.9 {regexp errors, -start bad int check} {
+    list [catch {regexp -start bogus {^$} {}} msg] $msg
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test regexp-7.1 {basic regsub operation} {
+    list [regsub aa+ xaxaaaxaa 111&222 foo] $foo
+} {1 xax111aaa222xaa}
+test regexp-7.2 {basic regsub operation} {
+    list [regsub aa+ aaaxaa &111 foo] $foo
+} {1 aaa111xaa}
+test regexp-7.3 {basic regsub operation} {
+    list [regsub aa+ xaxaaa 111& foo] $foo
+} {1 xax111aaa}
+test regexp-7.4 {basic regsub operation} {
+    list [regsub aa+ aaa 11&2&333 foo] $foo
+} {1 11aaa2aaa333}
+test regexp-7.5 {basic regsub operation} {
+    list [regsub aa+ xaxaaaxaa &2&333 foo] $foo
+} {1 xaxaaa2aaa333xaa}
+test regexp-7.6 {basic regsub operation} {
+    list [regsub aa+ xaxaaaxaa 1&22& foo] $foo
+} {1 xax1aaa22aaaxaa}
+test regexp-7.7 {basic regsub operation} {
+    list [regsub a(a+) xaxaaaxaa {1\122\1} foo] $foo
+} {1 xax1aa22aaxaa}
+test regexp-7.8 {basic regsub operation} {
+    list [regsub a(a+) xaxaaaxaa {1\\\122\1} foo] $foo
+} "1 {xax1\\aa22aaxaa}"
+test regexp-7.9 {basic regsub operation} {
+    list [regsub a(a+) xaxaaaxaa {1\\122\1} foo] $foo
+} "1 {xax1\\122aaxaa}"
+test regexp-7.10 {basic regsub operation} {
+    list [regsub a(a+) xaxaaaxaa {1\\&\1} foo] $foo
+} "1 {xax1\\aaaaaxaa}"
+test regexp-7.11 {basic regsub operation} {
+    list [regsub a(a+) xaxaaaxaa {1\&\1} foo] $foo
+} {1 xax1&aaxaa}
+test regexp-7.12 {basic regsub operation} {
+    list [regsub a(a+) xaxaaaxaa {\1\1\1\1&&} foo] $foo
+} {1 xaxaaaaaaaaaaaaaaxaa}
+test regexp-7.13 {basic regsub operation} {
+    set foo xxx
+    list [regsub abc xyz 111 foo] $foo
+} {0 xyz}
+test regexp-7.14 {basic regsub operation} {
+    set foo xxx
+    list [regsub ^ xyz "111 " foo] $foo
+} {1 {111 xyz}}
+test regexp-7.15 {basic regsub operation} {
+    set foo xxx
+    list [regsub -- -foo abc-foodef "111 " foo] $foo
+} {1 {abc111 def}}
+test regexp-7.16 {basic regsub operation} {
+    set foo xxx
+    list [regsub x "" y foo] $foo
+} {0 {}}
+#test regexp-7.17 {regsub utf compliance} {
+#    # if not UTF-8 aware, result is "0 1"
+#    set foo "xyz555ijka\u4e4ebpqr"
+#    regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar
+#    list [string compare $foo $bar] [regexp 4 $bar]
+#} {0 0}
+
+test regexp-8.1 {case conversion in regsub} {
+    list [regsub -nocase a(a+) xaAAaAAay & foo] $foo
+} {1 xaAAaAAay}
+test regexp-8.2 {case conversion in regsub} {
+    list [regsub -nocase a(a+) xaAAaAAay & foo] $foo
+} {1 xaAAaAAay}
+test regexp-8.3 {case conversion in regsub} {
+    set foo 123
+    list [regsub a(a+) xaAAaAAay & foo] $foo
+} {0 xaAAaAAay}
+test regexp-8.4 {case conversion in regsub} {
+    set foo 123
+    list [regsub -nocase a CaDE b foo] $foo
+} {1 CbDE}
+test regexp-8.5 {case conversion in regsub} {
+    set foo 123
+    list [regsub -nocase XYZ CxYzD b foo] $foo
+} {1 CbD}
+test regexp-8.6 {case conversion in regsub} {
+    set x abcdefghijklmnopqrstuvwxyz1234567890
+    set x $x$x$x$x$x$x$x$x$x$x$x$x
+    set foo 123
+    list [regsub -nocase $x $x b foo] $foo
+} {1 b}
+
+test regexp-9.1 {-all option to regsub} {
+    set foo 86
+    list [regsub -all x+ axxxbxxcxdx |&| foo] $foo
+} {4 a|xxx|b|xx|c|x|d|x|}
+test regexp-9.2 {-all option to regsub} {
+    set foo 86
+    list [regsub -nocase -all x+ aXxXbxxcXdx |&| foo] $foo
+} {4 a|XxX|b|xx|c|X|d|x|}
+test regexp-9.3 {-all option to regsub} {
+    set foo 86
+    list [regsub x+ axxxbxxcxdx |&| foo] $foo
+} {1 a|xxx|bxxcxdx}
+test regexp-9.4 {-all option to regsub} {
+    set foo 86
+    list [regsub -all bc axxxbxxcxdx |&| foo] $foo
+} {0 axxxbxxcxdx}
+test regexp-9.5 {-all option to regsub} {
+    set foo xxx
+    list [regsub -all node "node node more" yy foo] $foo
+} {2 {yy yy more}}
+test regexp-9.6 {-all option to regsub} {
+    set foo xxx
+    list [regsub -all ^ xxx 123 foo] $foo
+} {1 123xxx}
+
+test regexp-10.2 {newline sensitivity in regsub} {
+    set foo xxx
+    list [regsub -line {^a.*b$} "dabc\naxyb\n" 123 foo] $foo
+} "1 {dabc\n123\n}"
+test regexp-10.3 {newline sensitivity in regsub} {
+    set foo xxx
+    list [regsub -line {^a.*b$} "dabc\naxyb\nxb" 123 foo] $foo
+} "1 {dabc\n123\nxb}"
+#test regexp-10.4 {partial newline sensitivity in regsub} {
+#    set foo xxx
+#    list [regsub -lineanchor {^a.*b$} "da\naxyb\nxb" 123 foo] $foo
+#} "1 {da\n123}"
+#test regexp-10.5 {inverse partial newline sensitivity in regsub} {
+#    set foo xxx
+#    list [regsub -linestop {a.*b} "da\nbaxyb\nxb" 123 foo] $foo
+#} "1 {da\nb123\nxb}"
+
+test regexp-11.1 {regsub errors} jim {
+    list [catch {regsub a b} msg] $msg
+} {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}}
+test regexp-11.2 {regsub errors} jim {
+    list [catch {regsub -nocase a b} msg] $msg
+} {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}}
+test regexp-11.3 {regsub errors} jim {
+    list [catch {regsub -nocase -all a b} msg] $msg
+} {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}}
+test regexp-11.4 {regsub errors} jim {
+    list [catch {regsub a b c d e f} msg] $msg
+} {1 {wrong # args: should be "regsub ?switches? exp string subSpec ?varName?"}}
+test regexp-11.5 {regsub errors} jim {
+    list [catch {regsub -gorp a b c} msg] $msg
+} {1 {bad switch "-gorp": must be --, -all, -line, -nocase, or -start}}
+test regexp-11.6 {regsub errors} {
+    catch {regsub -nocase a( b c d} msg
+} 1
+test regexp-11.7 {regsub errors} jim {
+    catch {unset f1}
+    set f1 44
+    list [catch {regsub -nocase aaa aaa xxx f1(f2)} msg] $msg
+} {1 {can't set "f1(f2)": variable isn't array}}
+test regexp-11.8 {regsub errors, -start bad int check} {
+    list [catch {regsub -start bogus pattern string rep var} msg] $msg
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
+test regexp-11.9 {regsub without final variable name returns value} {
+    regsub b abaca X
+} {aXaca}
+test regexp-11.10 {regsub without final variable name returns value} {
+    regsub -all a abaca X
+} {XbXcX}
+
+test regexp-11.11 {regsub without final variable name returns value} {
+    regsub b(\[^d\]*)d abcdeabcfde {,&,\1,}
+} {a,bcd,c,eabcfde}
+test regexp-11.12 {regsub without final variable name returns value} {
+    regsub -all b(\[^d\]*)d abcdeabcfde {,&,\1,}
+} {a,bcd,c,ea,bcfd,cf,e}
+
+# This test crashes on the Mac unless you increase the Stack Space to about 1
+# Meg.  This is probably bigger than most users want... 
+# 8.2.3 regexp reduced stack space requirements, but this should be
+# tested again
+test regexp-12.1 {Tcl_RegExpExec: large number of subexpressions} {
+    list [regexp (.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) abcdefghijklmnopqrstuvwxyz all a b c d e f g h i j k l m n o p q r s t u v w x y z] $all $a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z
+} {1 abcdefghijklmnopqrstuvwxyz a b c d e f g h i j k l m n o p q r s t u v w x y z}
+
+test regexp-13.1 {regsub of a very large string} {
+    # This test is designed to stress the memory subsystem in order
+    # to catch Bug #933.  It only fails if the Tcl memory allocator
+    # is in use.
+
+    set line {BEGIN_TABLE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END_TABLE}
+    set filedata [string repeat $line 200]
+    for {set i 1} {$i<10} {incr i} {
+       regsub -all "BEGIN_TABLE " $filedata "" newfiledata
+    }
+    set x done
+} {done}
+
+test regexp-14.1 {CompileRegexp: regexp cache} {
+    regexp .*a b
+    regexp .*b c
+    regexp .*c d
+    regexp .*d e
+    regexp .*e f
+    set x .
+    append x *a
+    regexp $x bbba
+} 1
+test regexp-14.2 {CompileRegexp: regexp cache, different flags} {
+    regexp .*a b
+    regexp .*b c
+    regexp .*c d
+    regexp .*d e
+    regexp .*e f
+    set x .
+    append x *a
+    regexp -nocase $x bbba
+} 1
+
+#test regexp-15.1 {regexp -start} {
+#    catch {unset x}
+#    list [regexp -start -10 {\d} 1abc2de3 x] $x
+#} {1 1}
+#test regexp-15.2 {regexp -start} {
+#    catch {unset x}
+#    list [regexp -start 2 {\d} 1abc2de3 x] $x
+#} {1 2}
+#test regexp-15.3 {regexp -start} {
+#    catch {unset x}
+#    list [regexp -start 4 {\d} 1abc2de3 x] $x
+#} {1 2}
+#test regexp-15.4 {regexp -start} {
+#    catch {unset x}
+#    list [regexp -start 5 {\d} 1abc2de3 x] $x
+#} {1 3}
+test regexp-15.5 {regexp -start, over end of string} {
+    catch {unset x}
+    list [regexp -start [string length 1abc2de3] {\d} 1abc2de3 x] [info exists x]
+} {0 0}
+test regexp-15.6 {regexp -start, loss of ^$ behavior} {
+    list [regexp -start 2 {^$} {}]
+} {0}
+test regexp-15.7 {regexp -start, double option} {
+    regexp -start 2 -start 0 a abc
+} 1
+test regexp-15.8 {regexp -start, double option} {
+    regexp -start 0 -start 2 a abc
+} 0
+#test regexp-15.9 {regexp -start, end relative index} {
+#    catch {unset x}
+#    list [regexp -start end {\d} 1abc2de3 x] [info exists x]
+#} {0 0}
+#test regexp-15.10 {regexp -start, end relative index} {
+#    catch {unset x}
+#    list [regexp -start end-1 {\d} 1abc2de3 x] [info exists x] $x
+#} {1 1 3}
+#
+#test regexp-16.1 {regsub -start} {
+#    catch {unset x}
+#    list [regsub -all -start 2 {\d} a1b2c3d4e5 {/&} x] $x
+#} {4 a1b/2c/3d/4e/5}
+test regexp-16.2 {regsub -start} {
+    catch {unset x}
+    list [regsub -all -start -25 {z} hello {/&} x] $x
+} {0 hello}
+test regexp-16.3 {regsub -start} {
+    catch {unset x}
+    list [regsub -all -start 3 {z} hello {/&} x] $x
+} {0 hello}
+#test regexp-16.4 {regsub -start, \A behavior} {
+#    set out {}
+#    lappend out [regsub -start 0 -all {\A(\w)} {abcde} {/\1} x] $x
+#    lappend out [regsub -start 2 -all {\A(\w)} {abcde} {/\1} x] $x
+#} {5 /a/b/c/d/e 3 ab/c/d/e}
+test regexp-16.5 {regsub -start, double option} {
+    list [regsub -start 2 -start 0 a abc c x] $x
+} {1 cbc}
+test regexp-16.6 {regsub -start, double option} {
+    list [regsub -start 0 -start 2 a abc c x] $x
+} {0 abc}
+test regexp-16.7 {regexp -start, end relative index} {
+    list [regsub -start end a aaa b x] $x
+} {0 aaa}
+test regexp-16.8 {regexp -start, end relative index} {
+    list [regsub -start end-1 a aaa b x] $x
+} {1 aab}
+
+test regexp-17.1 {regexp -inline} {
+    regexp -inline b ababa
+} {b}
+test regexp-17.2 {regexp -inline} {
+    regexp -inline (b) ababa
+} {b b}
+test regexp-17.3 {regexp -inline -indices} {
+    regexp -inline -indices (b) ababa
+} {{1 1} {1 1}}
+#test regexp-17.4 {regexp -inline} {
+#    regexp -inline {\w(\d+)\w} "   hello 23 there456def "
+#} {e456d 456}
+#test regexp-17.5 {regexp -inline no matches} {
+#    regexp -inline {\w(\d+)\w} ""
+#} {}
+test regexp-17.6 {regexp -inline no matches} {
+    regexp -inline hello goodbye
+} {}
+test regexp-17.7 {regexp -inline, no matchvars allowed} {
+    list [catch {regexp -inline b abc match} msg] $msg
+} {1 {regexp match variables not allowed when using -inline}}
+
+test regexp-18.1 {regexp -all} {
+    regexp -all b bbbbb
+} {5}
+test regexp-18.2 {regexp -all} {
+    regexp -all b abababbabaaaaaaaaaab
+} {6}
+test regexp-18.3 {regexp -all -inline} {
+    regexp -all -inline b abababbabaaaaaaaaaab
+} {b b b b b b}
+#test regexp-18.4 {regexp -all -inline} {
+#    regexp -all -inline {\w(\w)} abcdefg
+#} {ab b cd d ef f}
+#test regexp-18.5 {regexp -all -inline} {
+#    regexp -all -inline {\w(\w)$} abcdefg
+#} {fg g}
+#test regexp-18.6 {regexp -all -inline} {
+#    regexp -all -inline {\d+} 10:20:30:40
+#} {10 20 30 40}
+test regexp-18.7 {regexp -all -inline} {
+    list [catch {regexp -all -inline b abc match} msg] $msg
+} {1 {regexp match variables not allowed when using -inline}}
+test regexp-18.8 {regexp -all} {
+    # This should not cause an infinite loop
+    regexp -all -inline {a*} a
+} {a}
+test regexp-18.9 {regexp -all} {
+    # Yes, the expected result is {a {}}.  Here's why:
+    # Start at index 0; a* matches the "a" there then stops.
+    # Go to index 1; a* matches the lambda (or {}) there then stops.  Recall
+    #   that a* matches zero or more "a"'s; thus it matches the string "b", as
+    #   there are zero or more "a"'s there.
+    # Go to index 2; this is past the end of the string, so stop.
+    regexp -all -inline {a*} ab
+} {a {}}
+test regexp-18.10 {regexp -all} {
+    # Yes, the expected result is {a {} a}.  Here's why:
+    # Start at index 0; a* matches the "a" there then stops.
+    # Go to index 1; a* matches the lambda (or {}) there then stops.   Recall
+    #   that a* matches zero or more "a"'s; thus it matches the string "b", as
+    #   there are zero or more "a"'s there.
+    # Go to index 2; a* matches the "a" there then stops.
+    # Go to index 3; this is past the end of the string, so stop.
+    regexp -all -inline {a*} aba
+} {a {} a}
+test regexp-18.11 {regexp -all} {
+    regexp -all -inline {^a} aaaa
+} {a}
+test regexp-18.12 {regexp -all -inline -indices} {
+    regexp -all -inline -indices a(b(c)d|e(f)g)h abcdhaefgh
+} {{0 4} {1 3} {2 2} {-1 -1} {5 9} {6 8} {-1 -1} {7 7}}
+
+test regexp-19.1 {regsub null replacement} {
+    regsub -all {@} {@hel@lo@} "\0a\0" result
+    list $result [string length $result]
+} "\0a\0hel\0a\0lo\0a\0 14"
+
+#test regexp-20.1 {regsub shared object shimmering} {
+#    # Bug #461322
+#    set a abcdefghijklmnopqurstuvwxyz 
+#    set b $a 
+#    set c abcdefghijklmnopqurstuvwxyz0123456789 
+#    regsub $a $c $b d 
+#    list $d [string length $d] [string bytelength $d]
+#} [list abcdefghijklmnopqurstuvwxyz0123456789 37 37]
+#test regexp-20.2 {regsub shared object shimmering with -about} {
+#    eval regexp -about abc
+#} {0 {}}
+
+test regexp-21.1 {regsub works with empty string} {
+    regsub -- ^ {} foo
+} {foo}
+
+test regexp-21.2 {regsub works with empty string} {
+    regsub -- \$ {} foo
+} {foo}
+
+test regexp-21.3 {regsub works with empty string offset} {
+    regsub -start 0 -- ^ {} foo
+} {foo}
+
+test regexp-21.4 {regsub works with empty string offset} {
+    regsub -start 0 -- \$ {} foo
+} {foo}
+
+test regexp-21.5 {regsub works with empty string offset} {
+    regsub -start 3 -- \$ {123} foo
+} {123foo}
+
+test regexp-21.6 {regexp works with empty string} {
+    regexp -- ^ {}
+} {1}
+
+test regexp-21.7 {regexp works with empty string} {
+    regexp -start 0 -- ^ {}
+} {1}
+
+test regexp-21.8 {regexp works with empty string offset} {
+    regexp -start 3 -- ^ {123}
+} {0}
+
+test regexp-21.9 {regexp works with empty string offset} {
+    regexp -start 3 -- \$ {123}
+} {1}
+
+#test regexp-21.10 {multiple matches handle newlines} {
+#    regsub -all -lineanchor -- {^#[^\n]*\n} "#one\n#two\n#three\n" foo\n
+#} "foo\nfoo\nfoo\n"
+
+test regexp-21.11 {multiple matches handle newlines} {
+    regsub -all -line -- ^ "a\nb\nc" \#
+} "\#a\n\#b\n\#c"
+
+test regexp-21.12 {multiple matches handle newlines} {
+    regsub -all -line -- ^ "\n\n" \#
+} "\#\n\#\n\#"
+
+test regexp-21.13 {multiple matches handle newlines} {
+    regexp -all -inline -indices -line -- ^ "a\nb\nc"
+} {{0 -1} {2 1} {4 3}}
+
+test regexp-21.14 {Literal newline in pattern} {
+    regexp -all -inline "\n(\[ \t\]+)" "\n\t\t# This  is  a test"
+} "{\n\t\t} {\t\t}"
+
+test regexp-22.1 {effect of caching} jim {
+
+    set filedata {BEGIN_TABLE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END_TABLE}
+
+       # Note: use 2 REs because often libc will cache a single regcomp() result
+
+       # t1 should be faster because the compiled re can be cached.
+       set re1 "END_TABLE"
+       set re2 "BEGIN_TABLE"
+
+       set t1 [time {
+               regexp -inline -all $re1 $filedata
+               regexp -inline -all $re2 $filedata
+       } 10000]
+
+       # t2 should be slower since the re's need to be recompiled every time
+       set t2 [time {
+               set re1 END
+               append re1 _TABLE
+               regexp -inline -all $re1 $filedata
+               set re2 BEGIN
+               append re2 _TABLE
+               regexp -inline -all $re2 $filedata
+       } 10000]
+
+       set t1 [lindex $t1 0]
+       set t2 [lindex $t2 0]
+
+       # If these two times are within 20% of each other, caching isn't working
+       expr {$t2 * 1.0 / $t1 < 1.2 && $t1 * 1.0 / $t2 < 1.2}
+} {0}
+
+testreport
diff --git a/jim/tests/regexp2.test b/jim/tests/regexp2.test
new file mode 100755 (executable)
index 0000000..165c187
--- /dev/null
@@ -0,0 +1,917 @@
+# Commands covered:  regexp, regsub
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id$
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd regexp
+testConstraint regexp_are [regexp {\d} 1]
+needs constraint regexp_are
+
+# Procedure to evaluate a script within a proc, to test compilation
+# functionality
+
+proc evalInProc { script } {
+    proc testProc {} $script
+    set status [catch {
+       testProc 
+    } result]
+    rename testProc {}
+    return $result
+    #return [list $status $result]
+}
+
+catch {unset foo}
+test regexpComp-1.1 {basic regexp operation} {
+    evalInProc {
+       regexp ab*c abbbc
+    }
+} 1
+test regexpComp-1.2 {basic regexp operation} {
+    evalInProc {
+       regexp ab*c ac
+    }
+} 1
+test regexpComp-1.3 {basic regexp operation} {
+    evalInProc {
+       regexp ab*c ab
+    }
+} 0
+test regexpComp-1.4 {basic regexp operation} {
+    evalInProc {
+       regexp -- -gorp abc-gorpxxx
+    }
+} 1
+test regexpComp-1.5 {basic regexp operation} {
+    evalInProc {
+       regexp {^([^ ]*)[ ]*([^ ]*)} "" a
+    }
+} 1
+test regexpComp-1.6 {basic regexp operation} {
+    list [catch {regexp {} abc} msg] $msg
+} {0 1}
+test regexpComp-1.7 {regexp utf compliance} {
+    # if not UTF-8 aware, result is "0 1"
+    evalInProc {
+       set foo "\u4e4eb q"
+       regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar
+       list [string compare $foo $bar] [regexp 4 $bar]
+    }
+} {0 0}
+
+test regexpComp-2.1 {getting substrings back from regexp} {
+    evalInProc {
+       set foo {}
+       list [regexp ab*c abbbbc foo] $foo
+    }
+} {1 abbbbc}
+test regexpComp-2.2 {getting substrings back from regexp} {
+    evalInProc {
+       set foo {}
+       set f2 {}
+       list [regexp a(b*)c abbbbc foo f2] $foo $f2
+    }
+} {1 abbbbc bbbb}
+test regexpComp-2.3 {getting substrings back from regexp} {
+    evalInProc {
+       set foo {}
+       set f2 {}
+       list [regexp a(b*)(c) abbbbc foo f2] $foo $f2
+    }
+} {1 abbbbc bbbb}
+test regexpComp-2.4 {getting substrings back from regexp} {
+    evalInProc {
+       set foo {}
+       set f2 {}
+       set f3 {}
+       list [regexp a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3
+    }
+} {1 abbbbc bbbb c}
+test regexpComp-2.5 {getting substrings back from regexp} {
+    evalInProc {
+       set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {};
+       set f6 {}; set f7 {}; set f8 {}; set f9 {}; set fa {}; set fb {};
+       list [regexp (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*)(a*)(b*) \
+               12223345556789999aabbb \
+               foo f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb] $foo $f1 $f2 $f3 $f4 $f5 \
+               $f6 $f7 $f8 $f9 $fa $fb
+    }
+} {1 12223345556789999aabbb 1 222 33 4 555 6 7 8 9999 aa bbb}
+test regexpComp-2.6 {getting substrings back from regexp} {
+    evalInProc {
+       set foo 2; set f2 2; set f3 2; set f4 2
+       list [regexp (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4
+    }
+} {1 a a {} {}}
+test regexpComp-2.7 {getting substrings back from regexp} {
+    evalInProc {
+       set foo 1; set f2 1; set f3 1; set f4 1
+       list [regexp (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4
+    }
+} {1 ac a {} c}
+test regexpComp-2.8 {getting substrings back from regexp} {
+    evalInProc {
+       set match {}
+       list [regexp {^a*b} aaaab match] $match
+    }
+} {1 aaaab}
+
+test regexpComp-3.1 {-indices option to regexp} {
+    evalInProc {
+       set foo {}
+       list [regexp -indices ab*c abbbbc foo] $foo
+    }
+} {1 {0 5}}
+test regexpComp-3.2 {-indices option to regexp} {
+    evalInProc {
+       set foo {}
+       set f2 {}
+       list [regexp -indices a(b*)c abbbbc foo f2] $foo $f2
+    }
+} {1 {0 5} {1 4}}
+test regexpComp-3.3 {-indices option to regexp} {
+    evalInProc {
+       set foo {}
+       set f2 {}
+       list [regexp -indices a(b*)(c) abbbbc foo f2] $foo $f2
+    }
+} {1 {0 5} {1 4}}
+test regexpComp-3.4 {-indices option to regexp} {
+    evalInProc {
+       set foo {}
+       set f2 {}
+       set f3 {}
+       list [regexp -indices a(b*)(c) abbbbc foo f2 f3] $foo $f2 $f3
+    }
+} {1 {0 5} {1 4} {5 5}}
+test regexpComp-3.5 {-indices option to regexp} {
+    evalInProc {
+       set foo {}; set f1 {}; set f2 {}; set f3 {}; set f4 {}; set f5 {};
+       set f6 {}; set f7 {}; set f8 {}; set f9 {}
+       list [regexp -indices (1*)(2*)(3*)(4*)(5*)(6*)(7*)(8*)(9*) \
+               12223345556789999 \
+               foo f1 f2 f3 f4 f5 f6 f7 f8 f9] $foo $f1 $f2 $f3 $f4 $f5 \
+               $f6 $f7 $f8 $f9
+    }
+} {1 {0 16} {0 0} {1 3} {4 5} {6 6} {7 9} {10 10} {11 11} {12 12} {13 16}}
+test regexpComp-3.6 {getting substrings back from regexp} {
+    evalInProc {
+       set foo 2; set f2 2; set f3 2; set f4 2
+       list [regexp -indices (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4
+    }
+} {1 {1 1} {1 1} {-1 -1} {-1 -1}}
+test regexpComp-3.7 {getting substrings back from regexp} {
+    evalInProc {
+       set foo 1; set f2 1; set f3 1; set f4 1
+       list [regexp -indices (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4
+    }
+} {1 {1 2} {1 1} {-1 -1} {2 2}}
+
+test regexpComp-4.1 {-nocase option to regexp} {
+    evalInProc {
+       regexp -nocase foo abcFOo
+    }
+} 1
+test regexpComp-4.2 {-nocase option to regexp} {
+    evalInProc {
+       set f1 22
+       set f2 33
+       set f3 44
+       list [regexp -nocase {a(b*)([xy]*)z} aBbbxYXxxZ22 f1 f2 f3] $f1 $f2 $f3
+    }
+} {1 aBbbxYXxxZ Bbb xYXxx}
+test regexpComp-4.3 {-nocase option to regexp} {
+    evalInProc {
+       regexp -nocase FOo abcFOo
+    }
+} 1
+set ::x abcdefghijklmnopqrstuvwxyz1234567890
+set ::x $x$x$x$x$x$x$x$x$x$x$x$x
+test regexpComp-4.4 {case conversion in regexp} {
+    evalInProc {
+       list [regexp -nocase $::x $::x foo] $foo
+    }
+} "1 $x"
+catch {unset ::x}
+
+test regexpComp-5.1 {exercise cache of compiled expressions} {
+    evalInProc {
+       regexp .*a b
+       regexp .*b c
+       regexp .*c d
+       regexp .*d e
+       regexp .*e f
+       regexp .*a bbba
+    }
+} 1
+test regexpComp-5.2 {exercise cache of compiled expressions} {
+    evalInProc {
+       regexp .*a b
+       regexp .*b c
+       regexp .*c d
+       regexp .*d e
+       regexp .*e f
+       regexp .*b xxxb
+    }
+} 1
+test regexpComp-5.3 {exercise cache of compiled expressions} {
+    evalInProc {
+       regexp .*a b
+       regexp .*b c
+       regexp .*c d
+       regexp .*d e
+       regexp .*e f
+       regexp .*c yyyc
+    }
+} 1
+test regexpComp-5.4 {exercise cache of compiled expressions} {
+    evalInProc {
+       regexp .*a b
+       regexp .*b c
+       regexp .*c d
+       regexp .*d e
+       regexp .*e f
+       regexp .*d 1d
+    }
+} 1
+test regexpComp-5.5 {exercise cache of compiled expressions} {
+    evalInProc {
+       regexp .*a b
+       regexp .*b c
+       regexp .*c d
+       regexp .*d e
+       regexp .*e f
+       regexp .*e xe
+    }
+} 1
+
+test regexpComp-6.4 {regexp errors} {
+    evalInProc {
+       list [catch {regexp a( b} msg] $msg
+    }
+} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
+test regexpComp-6.5 {regexp errors} {
+    evalInProc {
+       list [catch {regexp a( b} msg] $msg
+    }
+} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
+test regexpComp-6.6 {regexp errors} {
+    evalInProc {
+       list [catch {regexp a a f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1} msg] $msg
+    }
+} {0 1}
+test regexpComp-6.7 {regexp errors} {
+    evalInProc {
+       list [catch {regexp (x)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) xyzzy} msg] $msg
+    }
+} {0 0}
+test regexpComp-6.8 {regexp errors} {
+    evalInProc {
+       catch {unset f1}
+       set f1 44
+       catch {regexp abc abc f1(f2)} msg
+    }
+} {1}
+test regexpComp-6.9 {regexp errors, -start bad int check} {
+    evalInProc {
+       list [catch {regexp -start bogus {^$} {}} msg] $msg
+    }
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test regexpComp-7.1 {basic regsub operation} {
+    evalInProc {
+       list [regsub aa+ xaxaaaxaa 111&222 foo] $foo
+    }
+} {1 xax111aaa222xaa}
+test regexpComp-7.2 {basic regsub operation} {
+    evalInProc {
+       list [regsub aa+ aaaxaa &111 foo] $foo
+    }
+} {1 aaa111xaa}
+test regexpComp-7.3 {basic regsub operation} {
+    evalInProc {
+       list [regsub aa+ xaxaaa 111& foo] $foo
+    }
+} {1 xax111aaa}
+test regexpComp-7.4 {basic regsub operation} {
+    evalInProc {
+       list [regsub aa+ aaa 11&2&333 foo] $foo
+    }
+} {1 11aaa2aaa333}
+test regexpComp-7.5 {basic regsub operation} {
+    evalInProc {
+       list [regsub aa+ xaxaaaxaa &2&333 foo] $foo
+    }
+} {1 xaxaaa2aaa333xaa}
+test regexpComp-7.6 {basic regsub operation} {
+    evalInProc {
+       list [regsub aa+ xaxaaaxaa 1&22& foo] $foo
+    }
+} {1 xax1aaa22aaaxaa}
+test regexpComp-7.7 {basic regsub operation} {
+    evalInProc {
+       list [regsub a(a+) xaxaaaxaa {1\122\1} foo] $foo
+    }
+} {1 xax1aa22aaxaa}
+test regexpComp-7.8 {basic regsub operation} {
+    evalInProc {
+       list [regsub a(a+) xaxaaaxaa {1\\\122\1} foo] $foo
+    }
+} "1 {xax1\\aa22aaxaa}"
+test regexpComp-7.9 {basic regsub operation} {
+    evalInProc {
+       list [regsub a(a+) xaxaaaxaa {1\\122\1} foo] $foo
+    }
+} "1 {xax1\\122aaxaa}"
+test regexpComp-7.10 {basic regsub operation} {
+    evalInProc {
+       list [regsub a(a+) xaxaaaxaa {1\\&\1} foo] $foo
+    }
+} "1 {xax1\\aaaaaxaa}"
+test regexpComp-7.11 {basic regsub operation} {
+    evalInProc {
+       list [regsub a(a+) xaxaaaxaa {1\&\1} foo] $foo
+    }
+} {1 xax1&aaxaa}
+test regexpComp-7.12 {basic regsub operation} {
+    evalInProc {
+       list [regsub a(a+) xaxaaaxaa {\1\1\1\1&&} foo] $foo
+    }
+} {1 xaxaaaaaaaaaaaaaaxaa}
+test regexpComp-7.13 {basic regsub operation} {
+    evalInProc {
+       set foo xxx
+       list [regsub abc xyz 111 foo] $foo
+    }
+} {0 xyz}
+test regexpComp-7.14 {basic regsub operation} {
+    evalInProc {
+       set foo xxx
+       list [regsub ^ xyz "111 " foo] $foo
+    }
+} {1 {111 xyz}}
+test regexpComp-7.15 {basic regsub operation} {
+    evalInProc {
+       set foo xxx
+       list [regsub -- -foo abc-foodef "111 " foo] $foo
+    }
+} {1 {abc111 def}}
+test regexpComp-7.16 {basic regsub operation} {
+    evalInProc {
+       set foo xxx
+       list [regsub x "" y foo] $foo
+    }
+} {0 {}}
+test regexpComp-7.17 {regsub utf compliance} {
+    evalInProc {
+       # if not UTF-8 aware, result is "0 1"
+       set foo "xyz555ijka\u4e4ebpqr"
+       regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar
+       list [string compare $foo $bar] [regexp 4 $bar]
+    }
+} {0 0}
+
+test regexpComp-7.18 {regsub utf8 in char range} utf8 {
+    regsub {[\u4e4ex]b} xyza\u4e4ebijka\u4e4ebpqr 555
+} xyza555ijka\u4e4ebpqr
+
+test regexpComp-7.19 {regsub utf8 in complemented char range} utf8 {
+    regsub -all {[^x\u4e4e]b} xyza\u4e4ebizbjxbka\u4e4fbpqr 555
+} xyza\u4e4ebi555jxbka555pqr
+
+test regexpComp-8.1 {case conversion in regsub} {
+    evalInProc {
+       list [regsub -nocase a(a+) xaAAaAAay & foo] $foo
+    }
+} {1 xaAAaAAay}
+test regexpComp-8.2 {case conversion in regsub} {
+    evalInProc {
+       list [regsub -nocase a(a+) xaAAaAAay & foo] $foo
+    }
+} {1 xaAAaAAay}
+test regexpComp-8.3 {case conversion in regsub} {
+    evalInProc {
+       set foo 123
+       list [regsub a(a+) xaAAaAAay & foo] $foo
+    }
+} {0 xaAAaAAay}
+test regexpComp-8.4 {case conversion in regsub} {
+    evalInProc {
+       set foo 123
+       list [regsub -nocase a CaDE b foo] $foo
+    }
+} {1 CbDE}
+test regexpComp-8.5 {case conversion in regsub} {
+    evalInProc {
+       set foo 123
+       list [regsub -nocase XYZ CxYzD b foo] $foo
+    }
+} {1 CbD}
+test regexpComp-8.6 {case conversion in regsub} {
+    evalInProc {
+       set x abcdefghijklmnopqrstuvwxyz1234567890
+       set x $x$x$x$x$x$x$x$x$x$x$x$x
+       set foo 123
+       list [regsub -nocase $x $x b foo] $foo
+    }
+} {1 b}
+
+test regexpComp-9.1 {-all option to regsub} {
+    evalInProc {
+       set foo 86
+       list [regsub -all x+ axxxbxxcxdx |&| foo] $foo
+    }
+} {4 a|xxx|b|xx|c|x|d|x|}
+test regexpComp-9.2 {-all option to regsub} {
+    evalInProc {
+       set foo 86
+       list [regsub -nocase -all x+ aXxXbxxcXdx |&| foo] $foo
+    }
+} {4 a|XxX|b|xx|c|X|d|x|}
+test regexpComp-9.3 {-all option to regsub} {
+    evalInProc {
+       set foo 86
+       list [regsub x+ axxxbxxcxdx |&| foo] $foo
+    }
+} {1 a|xxx|bxxcxdx}
+test regexpComp-9.4 {-all option to regsub} {
+    evalInProc {
+       set foo 86
+       list [regsub -all bc axxxbxxcxdx |&| foo] $foo
+    }
+} {0 axxxbxxcxdx}
+test regexpComp-9.5 {-all option to regsub} {
+    evalInProc {
+       set foo xxx
+       list [regsub -all node "node node more" yy foo] $foo
+    }
+} {2 {yy yy more}}
+test regexpComp-9.6 {-all option to regsub} {
+    evalInProc {
+       set foo xxx
+       list [regsub -all ^ xxx 123 foo] $foo
+    }
+} {1 123xxx}
+
+#test regexpComp-10.1 {expanded syntax in regsub} {
+#    evalInProc {
+#      set foo xxx
+#      list [regsub -expanded ". \#comment\n  . \#comment2" abc def foo] $foo
+#    }
+#} {1 defc}
+test regexpComp-10.2 {newline sensitivity in regsub} {
+    evalInProc {
+       set foo xxx
+       list [regsub -line {^a.*b$} "dabc\naxyb\n" 123 foo] $foo
+    }
+} "1 {dabc\n123\n}"
+test regexpComp-10.3 {newline sensitivity in regsub} {
+    evalInProc {
+       set foo xxx
+       list [regsub -line {^a.*b$} "dabc\naxyb\nxb" 123 foo] $foo
+    }
+} "1 {dabc\n123\nxb}"
+#test regexpComp-10.4 {partial newline sensitivity in regsub} {
+#    evalInProc {
+#      set foo xxx
+#      list [regsub -lineanchor {^a.*b$} "da\naxyb\nxb" 123 foo] $foo
+#    }
+#} "1 {da\n123}"
+#test regexpComp-10.5 {inverse partial newline sensitivity in regsub} {
+#    evalInProc {
+#      set foo xxx
+#      list [regsub -linestop {a.*b} "da\nbaxyb\nxb" 123 foo] $foo
+#    }
+#} "1 {da\nb123\nxb}"
+
+#test regexpComp-11.1 {regsub errors} {
+#    evalInProc {
+#      list [catch {regsub a b} msg] $msg
+#    }
+#} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}}
+#test regexpComp-11.2 {regsub errors} {
+#    evalInProc {
+#      list [catch {regsub -nocase a b} msg] $msg
+#    }
+#} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}}
+#test regexpComp-11.3 {regsub errors} {
+#    evalInProc {
+#      list [catch {regsub -nocase -all a b} msg] $msg
+#    }
+#} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}}
+#test regexpComp-11.4 {regsub errors} {
+#    evalInProc {
+#      list [catch {regsub a b c d e f} msg] $msg
+#    }
+#} {1 {wrong # args: should be "regsub ?-switch ...? exp string subSpec ?varName?"}}
+#test regexpComp-11.5 {regsub errors} {
+#    evalInProc {
+#      list [catch {regsub -gorp a b c} msg] $msg
+#    }
+#} {1 {bad switch "-gorp": must be -all, -nocase, -expanded, -line, -linestop, -lineanchor, -start, or --}}
+#test regexpComp-11.6 {regsub errors} {
+#    evalInProc {
+#      list [catch {regsub -nocase a( b c d} msg] $msg
+#    }
+#} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
+test regexpComp-11.7 {regsub errors} {
+    evalInProc {
+       catch {unset f1}
+       set f1 44
+       catch {regsub -nocase aaa aaa xxx f1(f2)} msg
+    }
+} {1}
+test regexpComp-11.8 {regsub errors, -start bad int check} {
+    evalInProc {
+       list [catch {regsub -start bogus pattern string rep var} msg] $msg
+    }
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
+
+# This test crashes on the Mac unless you increase the Stack Space to about 1
+# Meg.  This is probably bigger than most users want... 
+# 8.2.3 regexp reduced stack space requirements, but this should be
+# tested again
+test regexpComp-12.1 {Tcl_RegExpExec: large number of subexpressions} {
+    evalInProc {
+       list [regexp (.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) abcdefghijklmnopqrstuvwxyz all a b c d e f g h i j k l m n o p q r s t u v w x y z] $all $a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z
+    }
+} {1 abcdefghijklmnopqrstuvwxyz a b c d e f g h i j k l m n o p q r s t u v w x y z}
+
+test regexpComp-13.1 {regsub of a very large string} {
+    # This test is designed to stress the memory subsystem in order
+    # to catch Bug #933.  It only fails if the Tcl memory allocator
+    # is in use.
+
+    set line {BEGIN_TABLE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END_TABLE}
+    set filedata [string repeat $line 200]
+    for {set i 1} {$i<10} {incr i} {
+       regsub -all "BEGIN_TABLE " $filedata "" newfiledata
+    }
+    set x done
+} {done}
+
+test regexpComp-14.1 {CompileRegexp: regexp cache} {
+    evalInProc {
+       regexp .*a b
+       regexp .*b c
+       regexp .*c d
+       regexp .*d e
+       regexp .*e f
+       set x .
+       append x *a
+       regexp $x bbba
+    }
+} 1
+test regexpComp-14.2 {CompileRegexp: regexp cache, different flags} {
+    evalInProc {
+       regexp .*a b
+       regexp .*b c
+       regexp .*c d
+       regexp .*d e
+       regexp .*e f
+       set x .
+       append x *a
+       regexp -nocase $x bbba
+    }
+} 1
+
+test regexpComp-15.1 {regexp -start} {
+    catch {unset x}
+    list [regexp -start -10 {\d} 1abc2de3 x] $x
+} {1 1}
+test regexpComp-15.2 {regexp -start} {
+    catch {unset x}
+    list [regexp -start 2 {\d} 1abc2de3 x] $x
+} {1 2}
+test regexpComp-15.3 {regexp -start} {
+    catch {unset x}
+    list [regexp -start 4 {\d} 1abc2de3 x] $x
+} {1 2}
+test regexpComp-15.4 {regexp -start} {
+    catch {unset x}
+    list [regexp -start 5 {\d} 1abc2de3 x] $x
+} {1 3}
+test regexpComp-15.5 {regexp -start, over end of string} {
+    catch {unset x}
+    list [regexp -start [string length 1abc2de3] {\d} 1abc2de3 x] [info exists x]
+} {0 0}
+test regexpComp-15.6 {regexp -start, loss of ^$ behavior} {
+    list [regexp -start 2 {^$} {}]
+} {0}
+
+test regexpComp-16.1 {regsub -start} {
+    catch {unset x}
+    list [regsub -all -start 2 {\d} a1b2c3d4e5 {/&} x] $x
+} {4 a1b/2c/3d/4e/5}
+test regexpComp-16.2 {regsub -start} {
+    catch {unset x}
+    list [regsub -all -start -25 {z} hello {/&} x] $x
+} {0 hello}
+test regexpComp-16.3 {regsub -start} {
+    catch {unset x}
+    list [regsub -all -start 3 {z} hello {/&} x] $x
+} {0 hello}
+#test regexpComp-16.4 {regsub -start, \A behavior} {
+#    set out {}
+#    lappend out [regsub -start 0 -all {\A(\w)} {abcde} {/\1} x] $x
+#    lappend out [regsub -start 2 -all {\A(\w)} {abcde} {/\1} x] $x
+#} {5 /a/b/c/d/e 3 ab/c/d/e}
+
+test regexpComp-17.1 {regexp -inline} {
+    regexp -inline b ababa
+} {b}
+test regexpComp-17.2 {regexp -inline} {
+    regexp -inline (b) ababa
+} {b b}
+test regexpComp-17.3 {regexp -inline -indices} {
+    regexp -inline -indices (b) ababa
+} {{1 1} {1 1}}
+test regexpComp-17.4 {regexp -inline} {
+    regexp -inline {\w(\d+)\w} "   hello 23 there456def "
+} {e456d 456}
+test regexpComp-17.5 {regexp -inline no matches} {
+    regexp -inline {\w(\d+)\w} ""
+} {}
+test regexpComp-17.6 {regexp -inline no matches} {
+    regexp -inline hello goodbye
+} {}
+test regexpComp-17.7 {regexp -inline, no matchvars allowed} {
+    list [catch {regexp -inline b abc match} msg] $msg
+} {1 {regexp match variables not allowed when using -inline}}
+
+test regexpComp-18.1 {regexp -all} {
+    regexp -all b bbbbb
+} {5}
+test regexpComp-18.2 {regexp -all} {
+    regexp -all b abababbabaaaaaaaaaab
+} {6}
+test regexpComp-18.3 {regexp -all -inline} {
+    regexp -all -inline b abababbabaaaaaaaaaab
+} {b b b b b b}
+test regexpComp-18.4 {regexp -all -inline} {
+    regexp -all -inline {\w(\w)} abcdefg
+} {ab b cd d ef f}
+test regexpComp-18.5 {regexp -all -inline} {
+    regexp -all -inline {\w(\w)$} abcdefg
+} {fg g}
+test regexpComp-18.6 {regexp -all -inline} {
+    regexp -all -inline {\d+} 10:20:30:40
+} {10 20 30 40}
+test regexpComp-18.7 {regexp -all -inline} {
+    list [catch {regexp -all -inline b abc match} msg] $msg
+} {1 {regexp match variables not allowed when using -inline}}
+test regexpComp-18.8 {regexp -all} {
+    # This should not cause an infinite loop
+    regexp -all -inline {a*} a
+} {a}
+test regexpComp-18.9 {regexp -all} {
+    # Yes, the expected result is {a {}}.  Here's why:
+    # Start at index 0; a* matches the "a" there then stops.
+    # Go to index 1; a* matches the lambda (or {}) there then stops.  Recall
+    #   that a* matches zero or more "a"'s; thus it matches the string "b", as
+    #   there are zero or more "a"'s there.
+    # Go to index 2; this is past the end of the string, so stop.
+    regexp -all -inline {a*} ab
+} {a {}}
+test regexpComp-18.10 {regexp -all} {
+    # Yes, the expected result is {a {} a}.  Here's why:
+    # Start at index 0; a* matches the "a" there then stops.
+    # Go to index 1; a* matches the lambda (or {}) there then stops.   Recall
+    #   that a* matches zero or more "a"'s; thus it matches the string "b", as
+    #   there are zero or more "a"'s there.
+    # Go to index 2; a* matches the "a" there then stops.
+    # Go to index 3; this is past the end of the string, so stop.
+    regexp -all -inline {a*} aba
+} {a {} a}
+test regexpComp-18.11 {regexp -all} {
+    evalInProc {
+       regexp -all -inline {^a} aaaa
+    }
+} {a}
+test regexpComp-18.12 {regexp -all -inline -indices} {
+    evalInProc {
+       regexp -all -inline -indices a(b(c)d|e(f)g)h abcdhaefgh
+    }
+} {{0 4} {1 3} {2 2} {-1 -1} {5 9} {6 8} {-1 -1} {7 7}}
+
+test regexpComp-19.1 {regsub null replacement} {
+    evalInProc {
+       regsub -all {@} {@hel@lo@} "\0a\0" result
+       list $result [string length $result]
+    }
+} "\0a\0hel\0a\0lo\0a\0 14"
+
+test regexpComp-20.1 {regsub shared object shimmering} {
+    evalInProc {
+       # Bug #461322
+       set a abcdefghijklmnopqurstuvwxyz 
+       set b $a 
+       set c abcdefghijklmnopqurstuvwxyz0123456789 
+       regsub $a $c $b d 
+       list $d [string length $d] [string bytelength $d]
+    }
+} [list abcdefghijklmnopqurstuvwxyz0123456789 37 37]
+#test regexpComp-20.2 {regsub shared object shimmering with -about} {
+#    evalInProc {
+#      eval regexp -about abc
+#    }
+#} {0 {}}
+
+test regexpComp-21.1 {regexp command compiling tests} {
+    evalInProc {
+       regexp foo bar
+    }
+} 0
+test regexpComp-21.2 {regexp command compiling tests} {
+    evalInProc {
+       regexp {^foo$} dogfood
+    }
+} 0
+test regexpComp-21.3 {regexp command compiling tests} {
+    evalInProc {
+       set a foo
+       regexp {^foo$} $a
+    }
+} 1
+test regexpComp-21.4 {regexp command compiling tests} {
+    evalInProc {
+       regexp foo dogfood
+    }
+} 1
+test regexpComp-21.5 {regexp command compiling tests} {
+    evalInProc {
+       regexp -nocase FOO dogfod
+    }
+} 0
+test regexpComp-21.6 {regexp command compiling tests} {
+    evalInProc {
+       regexp -n foo dogfoOd
+    }
+} 1
+test regexpComp-21.7 {regexp command compiling tests} {
+    evalInProc {
+       regexp -no -- FoO dogfood
+    }
+} 1
+test regexpComp-21.8 {regexp command compiling tests} {
+    evalInProc {
+       regexp -- foo dogfod
+    }
+} 0
+test regexpComp-21.9 {regexp command compiling tests} {
+    evalInProc {
+       list [catch {regexp -- -nocase foo dogfod} msg] $msg
+    }
+} {0 0}
+test regexpComp-21.10 {regexp command compiling tests} {
+    evalInProc {
+       list [regsub -all "" foo bar str] $str
+    }
+} {3 barfbarobaro}
+# This useless expression fails. Jim returns "bar"
+#test regexpComp-21.11 {regexp command compiling tests} {
+#    evalInProc {
+#      list [regsub -all "" "" bar str] $str
+#    }
+#} {0 {}}
+
+# We can forgive the underlying regexp engine for not supporting this.
+# Why not use this instead? "((^X)*|\$)"
+#test regexpComp-22.0.1 {Bug 1810038} {
+#    evalInProc {
+#      regexp ($|^X)* {}
+#    }
+#} 1
+
+set i 0
+foreach {str exp result} {
+    foo                ^foo            1
+    foobar     ^foobar$        1
+    foobar     bar$            1
+    foobar     ^$              0
+    ""         ^$              1
+    anything   $               1
+    anything   ^.*$            1
+    anything   ^.*a$           0
+    anything   ^.*a.*$         1
+    anything   ^.*.*$          1
+    anything   ^.*..*$         1
+    anything   ^.*b$           0
+    anything   ^a.*$           1
+} {
+    test regexpComp-22.[incr i] {regexp command compiling tests} \
+            [subst {evalInProc {set a "$str"; regexp {$exp} \$a}}] $result
+}
+
+set i 0
+foreach {str exp result} {
+    foo                ^foo            1
+    foobar     ^foobar$        1
+    foobar     bar$            1
+    foobar     ^$              0
+    ""         ^$              1
+    anything   $               1
+    anything   ^.*$            1
+    anything   ^.*a$           0
+    anything   ^.*a.*$         1
+    anything   ^.*.*$          1
+    anything   ^.*..*$         1
+    anything   ^.*b$           0
+    anything   ^a.*$           1
+} {
+    test regexpComp-23.[incr i] {regexp command compiling tests INST_REGEXP} \
+       [list regexp $exp $str] $result
+}
+
+test regexpComp-24.1 {regexp command compiling tests} {
+    evalInProc {
+       set re foo
+       regexp -nocase $re bar
+    }
+} 0
+test regexpComp-24.2 {regexp command compiling tests} {
+    evalInProc {
+       set re {^foo$}
+       regexp $re dogfood
+    }
+} 0
+test regexpComp-24.3 {regexp command compiling tests} {
+    evalInProc {
+       set a foo
+       set re {^foo$}
+       regexp $re $a
+    }
+} 1
+test regexpComp-24.4 {regexp command compiling tests} {
+    evalInProc {
+       set re foo
+       regexp $re dogfood
+    }
+} 1
+test regexpComp-24.5 {regexp command compiling tests} {
+    evalInProc {
+       set re FOO
+       regexp -nocase $re dogfod
+    }
+} 0
+test regexpComp-24.6 {regexp command compiling tests} {
+    evalInProc {
+       set re foo
+       regexp -n $re dogfoOd
+    }
+} 1
+test regexpComp-24.7 {regexp command compiling tests} {
+    evalInProc {
+       set re FoO
+       regexp -no -- $re dogfood
+    }
+} 1
+test regexpComp-24.8 {regexp command compiling tests} {
+    evalInProc {
+       set re foo
+       regexp -- $re dogfod
+    }
+} 0
+test regexpComp-24.9 {regexp command compiling tests} {
+    evalInProc {
+       set re "("
+       list [catch {regexp -- $re dogfod} msg] $msg
+    }
+} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
+test regexpComp-24.10 {regexp command compiling tests} {
+    # Bug 1902436 - last * escaped
+    evalInProc {
+       set text {this is *bold* !}
+       set re {\*bold\*}
+       regexp -- $re $text
+    }
+} 1
+test regexpComp-24.11 {regexp command compiling tests} {
+    # Bug 1902436 - last * escaped
+    evalInProc {
+       set text {this is *bold* !}
+       set re {\*bold\*.*!}
+       regexp -- $re $text
+    }
+} 1
+
+test regexp-25.1 {Repeat on escaped char} {
+    regexp {\x41\x42*} bc
+} 0
+
+test regexp-25.2 {Single braced count} {
+    regexp "a{4}" baaaad
+} 1
+
+testreport
diff --git a/jim/tests/regmin.test b/jim/tests/regmin.test
new file mode 100755 (executable)
index 0000000..ed4f1cd
--- /dev/null
@@ -0,0 +1,55 @@
+source [file dirname [info script]]/testing.tcl
+
+needs cmd regexp
+testConstraint regexp_are [regexp {\d} 1]
+needs constraint regexp_are
+
+test regexpmin-1.1 {Minimal +} {
+    regexp -inline {x(a|b|c)+?c} xabcabc
+} {xabc b}
+
+test regexpmin-1.2 {Maximal +} {
+    regexp -inline {x(a|b|c)+c} xabcabc
+} {xabcabc b}
+
+test regexpmin-1.3 {Minimal *} {
+    regexp -inline {x(a|b)*?} xababcabc
+} {x {}}
+
+test regexpmin-1.4 {Maximal *} {
+    regexp -inline {x(a|b)*} xababcabc
+} {xabab b}
+
+test regexpmin-1.5 {Maximal ?} {
+    regexp -inline {x(a|b)?} xababcabc
+} {xa a}
+
+test regexpmin-1.6 {Minimal ?} {
+    regexp -inline {x(a|b)??} xababcabc
+} {x {}}
+
+test regexpmin-1.7 {Maximal html} {
+       regexp -inline {<(.+)>} <foo><bar><grill>
+} {<foo><bar><grill> foo><bar><grill}
+
+test regexpmin-1.8 {Minimal html} {
+       regexp -inline {<(.+?)>} <foo><bar><grill>
+} {<foo> foo}
+
+test regexpmin-2.1 {utf8 repeat} utf8 {
+       regexp -inline {a\u00df+}  a\udf\udf\udf\udf\ub5z
+} "a\udf\udf\udf\udf"
+
+test regexpmin-2.2 {utf8 min repeat} utf8 {
+       regexp -inline {a\u00df+?}  a\udf\udf\udf\udf\ub5z
+} "a\udf"
+
+test regexpmin-3.1 {non-capturing paren} {
+    regexp -inline {x(?:a|b)?} xababcabc
+} {xa}
+
+test regexpmin-3.2 {non-capturing paren} {
+    regexp -inline {x(?:a|b)?.*(b|c)} xababcabc
+} {xababcabc c}
+
+testreport
diff --git a/jim/tests/rename.test b/jim/tests/rename.test
new file mode 100755 (executable)
index 0000000..617ea49
--- /dev/null
@@ -0,0 +1,155 @@
+# Commands covered:  rename
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: rename.test,v 1.8.2.1 2001/09/12 20:34:59 dgp Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+# Must eliminate the "unknown" command while the test is running,
+# especially if the test is being run in a program with its
+# own special-purpose unknown command.
+
+catch {rename unknown unknown.old}
+
+catch {rename r2 {}}
+proc r1 {} {return "procedure r1"}
+rename r1 r2
+test rename-1.1 {simple renaming} {
+    r2
+} {procedure r1}
+test rename-1.2 {simple renaming} {
+    list [catch r1 msg] $msg
+} {1 {invalid command name "r1"}}
+rename r2 {}
+test rename-1.3 {simple renaming} {
+    list [catch r2 msg] $msg
+} {1 {invalid command name "r2"}}
+
+# The test below is tricky because it renames a built-in command.
+# It's possible that the test procedure uses this command, so must
+# restore the command before calling test again.
+
+rename list l.new
+set a [catch list msg1]
+set b [l.new a b c]
+rename l.new list
+set c [catch l.new msg2]
+set d [list 111 222]
+test rename-2.1 {renaming built-in command} {
+    list $a $msg1 $b $c $msg2 $d
+} {1 {invalid command name "list"} {a b c} 1 {invalid command name "l.new"} {111 222}}
+
+test rename-3.1 {error conditions} {
+    list [catch {rename r1} msg] $msg
+} {1 {wrong # args: should be "rename oldName newName"}}
+test rename-3.2 {error conditions} {
+    list [catch {rename r1 r2 r3} msg] $msg
+} {1 {wrong # args: should be "rename oldName newName"}}
+test rename-3.3 {error conditions} {
+    proc r1 {} {}
+    proc r2 {} {}
+    list [catch {rename r1 r2} msg] $msg
+} {1 {can't rename to "r2": command already exists}}
+test rename-3.4 {error conditions} {
+    catch {rename r1 {}}
+    catch {rename r2 {}}
+    list [catch {rename r1 r2} msg] $msg
+} {1 {can't rename "r1": command doesn't exist}}
+test rename-3.5 {error conditions} {
+    catch {rename _non_existent_command {}}
+    list [catch {rename _non_existent_command {}} msg] $msg
+} {1 {can't delete "_non_existent_command": command doesn't exist}}
+
+catch {rename unknown {}}
+catch {rename unknown.old unknown}
+
+if {[info command testdel] == "testdel"} {
+    test rename-4.1 {reentrancy issues with command deletion and renaming} {
+       set x {}
+       testdel {} foo {lappend x deleted; rename bar {}; lappend x [info command bar]}
+       rename foo bar
+       lappend x |
+       rename bar {}
+       set x
+    } {| deleted {}}
+    test rename-4.2 {reentrancy issues with command deletion and renaming} {
+       set x {}
+       testdel {} foo {lappend x deleted; rename foo bar}
+       rename foo {}
+       set x
+    } {deleted}
+    test rename-4.3 {reentrancy issues with command deletion and renaming} {
+       set x {}
+       testdel {} foo {lappend x deleted; testdel {} foo {lappend x deleted2}}
+       rename foo {}
+       lappend x |
+       rename foo {}
+       set x
+    } {deleted | deleted2}
+    test rename-4.4 {reentrancy issues with command deletion and renaming} {
+       set x {}
+       testdel {} foo {lappend x deleted; rename foo bar}
+       rename foo {}
+       lappend x | [info command bar]
+    } {deleted | {}}
+    test rename-4.5 {reentrancy issues with command deletion and renaming} {
+       set env(value) before
+       interp create foo
+       testdel foo cmd {set env(value) deleted}
+       interp delete foo
+       set env(value)
+    } {deleted}
+    test rename-4.6 {reentrancy issues with command deletion and renaming} {
+       proc killx args {
+           interp delete foo
+       }
+       set env(value) before
+       interp create foo
+       foo alias killx killx
+       testdel foo cmd {set env(value) deleted; killx}
+       list [catch {foo eval {rename cmd {}}} msg] $msg $env(value)
+    } {0 {} deleted}
+    test rename-4.7 {reentrancy issues with command deletion and renaming} {
+       proc killx args {
+           interp delete foo
+       }
+       set env(value) before
+       interp create foo
+       foo alias killx killx
+       testdel foo cmd {set env(value) deleted; killx}
+       list [catch {interp delete foo} msg] $msg $env(value)
+    } {0 {} deleted}
+    if {[info exists env(value)]} {
+       unset env(value)
+    }
+}
+
+test rename-6.1 {old code invalidated (epoch incremented) when cmd with compile proc is renamed } {
+    proc x {} {
+        set a 123
+        set b [split a 2]
+    }
+    x
+    rename split split.old
+    proc split {} {puts "new split called!"}
+    catch {x} msg
+} 1
+
+if {[info commands split.old] != {}} {
+    catch {rename split {}}
+    catch {rename split.old split}
+}
+catch {rename x {}}
+catch {rename killx {}}
+
+testreport
diff --git a/jim/tests/return-break.tcl b/jim/tests/return-break.tcl
new file mode 100755 (executable)
index 0000000..bbc7715
--- /dev/null
@@ -0,0 +1 @@
+return -code break result
diff --git a/jim/tests/return.test b/jim/tests/return.test
new file mode 100755 (executable)
index 0000000..94e38a3
--- /dev/null
@@ -0,0 +1,50 @@
+source [file dirname [info script]]/testing.tcl
+
+# return -code
+
+test return-1.1 {return -code} {
+       set script "return -code 4 result"
+       list [catch {eval $script} msg] $msg
+} {2 result}
+
+test return-1.2 {source file with break} {
+       list [catch {source break.tcl} msg] $msg
+} {3 {}}
+
+test return-1.3 {source file with break} {
+       list [catch {source return-break.tcl} msg] $msg
+} {3 result}
+
+proc a {level code msg} {
+       return -level $level -code $code $msg
+}
+
+proc b {level code msg} {
+       a $level $code $msg
+}
+
+test return-2.1 {return -level 0} {
+       list [catch {a 0 20 text} msg] $msg
+} {20 text}
+
+test return-2.2 {return -level 1} {
+       list [catch {a 1 20 text} msg] $msg
+} {20 text}
+
+test return-2.3 {return -level 2} {
+       list [catch {a 2 20 text} msg] $msg
+} {2 text}
+
+test return-2.4 {return -level 0} {
+       list [catch {b 0 20 text} msg] $msg
+} {20 text}
+
+test return-2.5 {return -level 1} {
+       list [catch {b 1 20 text} msg] $msg
+} {20 text}
+
+test return-2.6 {return -level 2} {
+       list [catch {b 2 20 text} msg] $msg
+} {20 text}
+
+testreport
diff --git a/jim/tests/scan.test b/jim/tests/scan.test
new file mode 100755 (executable)
index 0000000..2267d22
--- /dev/null
@@ -0,0 +1,673 @@
+# Commands covered:  scan
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: scan.test,v 1.10.2.2 2002/02/07 01:54:04 hobbs Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd scan
+
+test scan-1.1 {BuildCharSet, CharInSet} {
+    list [scan foo {%[^o]} x] $x
+} {1 f}
+test scan-1.2 {BuildCharSet, CharInSet} {
+    list [scan \]foo {%[]f]} x] $x
+} {1 \]f}
+test scan-1.3 {BuildCharSet, CharInSet} {
+    list [scan abc-def {%[a-c]} x] $x
+} {1 abc}
+test scan-1.4 {BuildCharSet, CharInSet} {
+    list [scan abc-def {%[a-c]} x] $x
+} {1 abc}
+test scan-1.5 {BuildCharSet, CharInSet} {
+    list [scan -abc-def {%[-ac]} x] $x
+} {1 -a}
+test scan-1.6 {BuildCharSet, CharInSet} {
+    list [scan -abc-def {%[ac-]} x] $x
+} {1 -a}
+test scan-1.7 {BuildCharSet, CharInSet} {
+    list [scan abc-def {%[c-a]} x] $x
+} {1 abc}
+test scan-1.8 {BuildCharSet, CharInSet} {
+    list [scan def-abc {%[^c-a]} x] $x
+} {1 def-}
+test scan-1.9 {BuildCharSet, CharInSet no match} {
+    catch {unset x}
+    list [scan {= f} {= %[TF]} x] [info exists x]
+} {0 0}
+
+test scan-2.1 {ReleaseCharSet} {
+    list [scan abcde {%[abc]} x] $x
+} {1 abc}
+test scan-2.2 {ReleaseCharSet} {
+    list [scan abcde {%[a-c]} x] $x
+} {1 abc}
+
+test scan-3.1 {ValidateFormat} {
+    list [catch {scan {} {%d%1$d} x} msg] $msg
+} {1 {cannot mix "%" and "%n$" conversion specifiers}}
+test scan-3.2 {ValidateFormat} {
+    list [catch {scan {} {%d%1$d} x} msg] $msg
+} {1 {cannot mix "%" and "%n$" conversion specifiers}}
+test scan-3.3 {ValidateFormat} {
+    list [catch {scan {} {%2$d%d} x} msg] $msg
+} {1 {"%n$" argument index out of range}}
+test scan-3.4 {ValidateFormat} {
+    # degenerate case, before changed from 8.2 to 8.3
+    list [catch {scan {} %d} msg] $msg
+} {0 {}}
+test scan-3.5 {ValidateFormat} {
+    list [catch {scan {} {%10c} a} msg] $msg
+} {1 {field width may not be specified in %c conversion}}
+test scan-3.6 {ValidateFormat} jim {
+    list [catch {scan {} {%*1$d} a} msg] $msg
+} {1 {bad scan conversion character}}
+test scan-3.7 {ValidateFormat} {
+    list [catch {scan {} {%1$d%1$d} a} msg] $msg
+} {1 {variable is assigned by multiple "%n$" conversion specifiers}}
+test scan-3.8 {ValidateFormat} {
+    list [catch {scan {} a x} msg] $msg
+} {1 {variable is not assigned by any conversion specifiers}}
+test scan-3.9 {ValidateFormat} {
+    list [catch {scan {} {%2$s} x y} msg] $msg
+} {1 {variable is not assigned by any conversion specifiers}}
+test scan-3.10 {ValidateFormat} {
+    list [catch {scan {} {%[a} x} msg] $msg
+} {1 {unmatched [ in format string}}
+test scan-3.11 {ValidateFormat} {
+    list [catch {scan {} {%[^a} x} msg] $msg
+} {1 {unmatched [ in format string}}
+test scan-3.12 {ValidateFormat} {
+    list [catch {scan {} {%[]a} x} msg] $msg
+} {1 {unmatched [ in format string}}
+test scan-3.13 {ValidateFormat} {
+    list [catch {scan {} {%[^]a} x} msg] $msg
+} {1 {unmatched [ in format string}}
+
+test scan-4.1 {Tcl_ScanObjCmd, argument checks} jim {
+    list [catch {scan} msg] $msg
+} {1 {wrong # args: should be "scan string format ?varName varName ...?"}}
+test scan-4.2 {Tcl_ScanObjCmd, argument checks} jim {
+    list [catch {scan string} msg] $msg
+} {1 {wrong # args: should be "scan string format ?varName varName ...?"}}
+test scan-4.3 {Tcl_ScanObjCmd, argument checks} {
+    # degenerate case, before changed from 8.2 to 8.3
+    list [catch {scan string format} msg] $msg
+} {0 {}}
+test scan-4.4 {Tcl_ScanObjCmd, whitespace} {
+    list [scan {   abc   def   } {%s%s} x y] $x $y
+} {2 abc def}
+test scan-4.5 {Tcl_ScanObjCmd, whitespace} {
+    list [scan {   abc   def   } { %s %s } x y] $x $y
+} {2 abc def}
+test scan-4.6 {Tcl_ScanObjCmd, whitespace} {
+    list [scan {   abc   def   } { %s %s } x y] $x $y
+} {2 abc def}
+test scan-4.7 {Tcl_ScanObjCmd, literals} {
+    # degenerate case, before changed from 8.2 to 8.3
+    scan {   abc   def   } { abc def }
+} {}
+test scan-4.8 {Tcl_ScanObjCmd, literals} {
+    set x {}
+    list [scan {   abcg} { abc def %1s} x] $x
+} {0 {}}
+test scan-4.9 {Tcl_ScanObjCmd, literals} {
+    list [scan {   abc%defghi} { abc %% def%n } x] $x
+} {1 10}
+test scan-4.10 {Tcl_ScanObjCmd, assignment suppression} {
+    list [scan {   abc   def   } { %*c%s def } x] $x
+} {1 bc}
+test scan-4.11 {Tcl_ScanObjCmd, XPG3-style} {
+    list [scan {   abc   def   } {%2$s %1$s} x y] $x $y
+} {2 def abc}
+test scan-4.12 {Tcl_ScanObjCmd, width specifiers} {
+    list [scan {abc123456789012} {%3s%3d%3f%3[0-9]%s} a b c d e] $a $b $c $d $e
+} {5 abc 123 456.0 789 012}
+test scan-4.13 {Tcl_ScanObjCmd, width specifiers} {
+    list [scan {abc123456789012} {%3s%3d%3f%3[0-9]%s} a b c d e] $a $b $c $d $e
+} {5 abc 123 456.0 789 012}
+test scan-4.14 {Tcl_ScanObjCmd, underflow} {
+    set x {}
+    list [scan {a} {a%d} x] $x
+} {-1 {}}
+test scan-4.15 {Tcl_ScanObjCmd, underflow} {
+    set x {}
+    list [scan {} {a%d} x] $x
+} {-1 {}}
+test scan-4.16 {Tcl_ScanObjCmd, underflow} {
+    set x {}
+    list [scan {ab} {a%d} x] $x
+} {0 {}}
+test scan-4.17 {Tcl_ScanObjCmd, underflow} {
+    set x {}
+    list [scan {a   } {a%d} x] $x
+} {-1 {}}
+test scan-4.18 {Tcl_ScanObjCmd, skipping whitespace} {
+    list [scan {  b} {%c%s} x y] $x $y
+} {2 32 b}
+test scan-4.19 {Tcl_ScanObjCmd, skipping whitespace} {
+    list [scan {  b} {%[^b]%s} x y] $x $y
+} {2 {  } b}
+test scan-4.20 {Tcl_ScanObjCmd, string scanning} {
+    list [scan {abc def} {%s} x] $x
+} {1 abc}
+test scan-4.21 {Tcl_ScanObjCmd, string scanning} {
+    list [scan {abc def} {%0s} x] $x
+} {1 abc}
+test scan-4.22 {Tcl_ScanObjCmd, string scanning} {
+    list [scan {abc def} {%2s} x] $x
+} {1 ab}
+test scan-4.23 {Tcl_ScanObjCmd, string scanning} {
+    list [scan {abc def} {%*s%n} x] $x
+} {1 3}
+test scan-4.24 {Tcl_ScanObjCmd, charset scanning} {
+    list [scan {abcdef} {%[a-c]} x] $x
+} {1 abc}
+test scan-4.25 {Tcl_ScanObjCmd, charset scanning} {
+    list [scan {abcdef} {%0[a-c]} x] $x
+} {1 abc}
+test scan-4.26 {Tcl_ScanObjCmd, charset scanning} {
+    list [scan {abcdef} {%2[a-c]} x] $x
+} {1 ab}
+test scan-4.27 {Tcl_ScanObjCmd, charset scanning} {
+    list [scan {abcdef} {%*[a-c]%n} x] $x
+} {1 3}
+test scan-4.28 {Tcl_ScanObjCmd, character scanning} {
+    list [scan {abcdef} {%c} x] $x
+} {1 97}
+test scan-4.29 {Tcl_ScanObjCmd, character scanning} {
+    list [scan {abcdef} {%*c%n} x] $x
+} {1 1}
+
+test scan-4.30 {Tcl_ScanObjCmd, base-10 integer scanning} {
+    set x {}
+    list [scan {1234567890a} {%3d} x] $x
+} {1 123}
+test scan-4.31 {Tcl_ScanObjCmd, base-10 integer scanning} {
+    set x {}
+    list [scan {1234567890a} {%d} x] $x
+} {1 1234567890}
+test scan-4.32 {Tcl_ScanObjCmd, base-10 integer scanning} {
+    set x {}
+    list [scan {01234567890a} {%d} x] $x
+} {1 1234567890}
+test scan-4.33 {Tcl_ScanObjCmd, base-10 integer scanning} {
+    set x {}
+    list [scan {+01234} {%d} x] $x
+} {1 1234}
+test scan-4.34 {Tcl_ScanObjCmd, base-10 integer scanning} {
+    set x {}
+    list [scan {-01234} {%d} x] $x
+} {1 -1234}
+test scan-4.35 {Tcl_ScanObjCmd, base-10 integer scanning} {
+    set x {}
+    list [scan {a01234} {%d} x] $x
+} {0 {}}
+test scan-4.36 {Tcl_ScanObjCmd, base-10 integer scanning} {
+    set x {}
+    list [scan {0x10} {%d} x] $x
+} {1 0}
+test scan-4.37 {Tcl_ScanObjCmd, base-8 integer scanning} {
+    set x {}
+    list [scan {012345678} {%o} x] $x
+} {1 342391}
+test scan-4.38 {Tcl_ScanObjCmd, base-8 integer scanning} {
+    set x {}
+    list [scan {+1238 -1239 123a} {%o%*s%o%*s%o} x y z] $x $y $z
+} {3 83 -83 83}
+test scan-4.39 {Tcl_ScanObjCmd, base-16 integer scanning} {
+    set x {}
+    list [scan {+1238 -123a 0123} {%x%x%x} x y z] $x $y $z
+} {3 4664 -4666 291}
+test scan-4.40 {Tcl_ScanObjCmd, base-16 integer scanning} {
+    # The behavior changed in 8.4a4/8.3.4cvs (6 Feb) to correctly
+    # return '1' for 0x1 scanned via %x, to comply with 8.0 and C scanf.
+    # Bug #495213
+    set x {}
+    list [scan {aBcDeF AbCdEf 0x1} {%x%x%x} x y z] $x $y $z
+} {3 11259375 11259375 1}
+test scan-4.40.1 {Tcl_ScanObjCmd, base-16 integer scanning} {
+    set x {}
+    list [scan {0xF 0x00A0B 0X0XF} {%x %x %x} x y z] $x $y $z
+} {3 15 2571 0}
+test scan-4.40.2 {Tcl_ScanObjCmd, base-16 integer scanning} {
+    catch {unset x}
+    list [scan {xF} {%x} x] [info exists x]
+} {0 0}
+test scan-4.41 {Tcl_ScanObjCmd, base-unknown integer scanning} {
+    set x {}
+    list [scan {10 010 0x10} {%i%i%i} x y z] $x $y $z
+} {3 10 10 16}
+test scan-4.42 {Tcl_ScanObjCmd, base-unknown integer scanning} {
+    set x {}
+    list [scan {10 010 0X10} {%i%i%i} x y z] $x $y $z
+} {3 10 10 16}
+test scan-4.43 {Tcl_ScanObjCmd, integer scanning, odd cases} {
+    set x {}
+    list [scan {+ } {%i} x] $x
+} {0 {}}
+#test scan-4.44 {Tcl_ScanObjCmd, integer scanning, odd cases} {
+#    set x {}
+#    list [scan {+} {%i} x] $x
+#} {-1 {}}
+test scan-4.45 {Tcl_ScanObjCmd, integer scanning, odd cases} {
+    set x {}
+    list [scan {0x} {%i%s} x y] $x $y
+} {2 0 x}
+test scan-4.46 {Tcl_ScanObjCmd, integer scanning, odd cases} {
+    set x {}
+    list [scan {0X} {%i%s} x y] $x $y
+} {2 0 X}
+test scan-4.47 {Tcl_ScanObjCmd, integer scanning, suppressed} {
+    set x {}
+    list [scan {123def} {%*i%s} x] $x
+} {1 def}
+test scan-4.48 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {1 2 3} {%e %f %g} x y z] $x $y $z
+} {3 1.0 2.0 3.0}
+test scan-4.49 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {.1 0.2 3.} {%e %f %g} x y z] $x $y $z
+} {3 0.1 0.2 3.0}
+test scan-4.50 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {1234567890a} %f x] $x
+} {1 1234567890.0}
+test scan-4.51 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {+123+45} %f x] $x
+} {1 123.0}
+test scan-4.52 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {-123+45} %f x] $x
+} {1 -123.0}
+test scan-4.53 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {1.0e1} %f x] $x
+} {1 10.0}
+test scan-4.54 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {1.0e-1} %f x] $x
+} {1 0.1}
+#test scan-4.55 {Tcl_ScanObjCmd, odd cases} {
+#    set x {}
+#    list [scan {+} %f x] $x
+#} {-1 {}}
+test scan-4.56 {Tcl_ScanObjCmd, odd cases} {
+    set x {}
+    list [scan {1.0e} %f%s x y] $x $y
+} {2 1.0 e}
+test scan-4.57 {Tcl_ScanObjCmd, odd cases} {
+    set x {}
+    list [scan {1.0e+} %f%s x y] $x $y
+} {2 1.0 e+}
+test scan-4.58 {Tcl_ScanObjCmd, odd cases} {
+    set x {}
+    set y {}
+    list [scan {e1} %f%s x y] $x $y
+} {0 {} {}}
+test scan-4.59 {Tcl_ScanObjCmd, float scanning} {
+    list [scan {1.0e-1x} %*f%n x] $x
+} {1 6}
+
+test scan-4.60 {Tcl_ScanObjCmd, set errors} {
+    set x {}
+    set y {}
+    set z 1
+    set result [list [catch {scan {abc def ghi} {%s%s%s} x z(z) y} msg] \
+           $x $y]
+    set result
+} {1 abc ghi}
+test scan-4.61 {Tcl_ScanObjCmd, set errors} {
+    set x {}
+    set y 1
+    set z 1
+    set result [list [catch {scan {abc def ghi} {%s%s%s} x y(y) z(z)} msg] \
+           $x]
+    set result
+} {1 abc}
+
+# procedure that returns the range of integers
+
+# On Tcl with bignum, these won't produce a result!
+proc int_range {} {
+    for { set MIN_INT 1 } { $MIN_INT > 0 } {} {
+       set MIN_INT [expr { $MIN_INT << 1 }]
+    }
+    set MAX_INT [expr { ~ $MIN_INT }]
+    return [list $MIN_INT $MAX_INT]
+}
+
+test scan-4.62 {scanning of large and negative octal integers} jim {
+    foreach { MIN_INT MAX_INT } [int_range] {}
+    set scanstring [format {%o %o %o} -1 $MIN_INT $MAX_INT]
+    list [scan $scanstring {%o %o %o} a b c] \
+       [expr { $a == -1 }] [expr { $b == $MIN_INT }] [expr { $c == $MAX_INT }]
+} {3 1 1 1}
+test scan-4.63 {scanning of large and negative hex integers} jim {
+    foreach { MIN_INT MAX_INT } [int_range] {}
+    set scanstring [format {%x %x %x} -1 $MIN_INT $MAX_INT]
+    list [scan $scanstring {%x %x %x} a b c] \
+       [expr { $a == -1 }] [expr { $b == $MIN_INT }] [expr { $c == $MAX_INT }]
+} {3 1 1 1}
+
+# clean up from last two tests
+
+catch {
+    rename int_range {}
+}
+
+test scan-5.1 {integer scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "-20 1476 \n33 0" "%d %d %d %d" a b c d] $a $b $c $d
+} {4 -20 1476 33 0}
+test scan-5.2 {integer scanning} {
+    set a {}; set b {}; set c {}
+    list [scan "-45 16 7890 +10" "%2d %*d %10d %d" a b c] $a $b $c
+} {3 -4 16 7890}
+test scan-5.3 {integer scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "-45 16 +10 987" "%ld %d %ld %d" a b c d] $a $b $c $d
+} {4 -45 16 10 987}
+test scan-5.4 {integer scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "14 1ab 62 10" "%d %x %lo %x" a b c d] $a $b $c $d
+} {4 14 427 50 16}
+test scan-5.5 {integer scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "12345670 1234567890ab cdefg" "%o        %o %x %lx" a b c d] \
+           $a $b $c $d
+} {4 2739128 342391 561323 52719}
+test scan-5.6 {integer scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "ab123-24642" "%2x %3x %3o %2o" a b c d] $a $b $c $d
+} {4 171 291 -20 52}
+test scan-5.7 {integer scanning} {
+    set a {}; set b {}
+    list [scan "1234567 234 567  " "%*3x %x %*o %4o" a b] $a $b
+} {2 17767 375}
+test scan-5.8 {integer scanning} {
+    set a {}; set b {}
+    list [scan "a      1234" "%d %d" a b] $a $b
+} {0 {} {}}
+test scan-5.9 {integer scanning} {
+    set a {}; set b {}; set c {}; set d {};
+    list [scan "12345678" "%2d %2d %2ld %2d" a b c d] $a $b $c $d
+} {4 12 34 56 78}
+test scan-5.10 {integer scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "1 2 " "%hd %d %d %d" a b c d] $a $b $c $d
+} {2 1 2 {} {}}
+#
+# The behavior for scaning intergers larger than MAX_INT is
+# not defined by the ANSI spec.  Some implementations wrap the
+# input (-16) some return MAX_INT.
+#
+test scan-5.11 {integer scanning} {
+    set a {}; set b {};
+    list [scan "4294967280 4294967280" "%u %d" a b] $a \
+           [expr {$b == -16 || $b == 0x7fffffff || $b == $a}]
+} {2 4294967280 1}
+
+test scan-6.1 {floating-point scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "2.1 -3.0e8 .99962 a" "%f%g%e%f" a b c d] $a $b $c $d
+} {3 2.1 -300000000.0 0.99962 {}}
+test scan-6.2 {floating-point scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "-1.2345 +8.2 9" "%3e %3lf %f %f" a b c d] $a $b $c $d
+} {4 -1.0 234.0 5.0 8.2}
+test scan-6.3 {floating-point scanning} {
+    set a {}; set b {}; set c {}
+    list [scan "1e00004 332E-4 3e+4" "%Lf %*2e %f %f" a b c] $a $c
+} {3 10000.0 30000.0}
+#
+# Some libc implementations consider 3.e- bad input.  The ANSI
+# spec states that digits must follow the - sign.
+#
+test scan-6.4 {floating-point scanning} {
+    set a {}; set b {}; set c {}
+    list [scan "1. 47.6 2.e2 3.e-" "%f %*f %f %f" a b c] $a $b $c
+} {3 1.0 200.0 3.0}
+test scan-6.5 {floating-point scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "4.6 99999.7 876.43e-1 118" "%f %f %f %e" a b c d] $a $b $c $d
+} {4 4.6 99999.7 87.643 118.0}
+test scan-6.6 {floating-point scanning} jim {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "1.2345 697.0e-3 124 .00005" "%f %e %f %e" a b c d] $a $b $c $d
+} {4 1.2345 0.697 124.0 5e-05}
+test scan-6.7 {floating-point scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "4.6abc" "%f %f %f %f" a b c d] $a $b $c $d
+} {1 4.6 {} {} {}}
+test scan-6.8 {floating-point scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "4.6 5.2" "%f %f %f %f" a b c d] $a $b $c $d
+} {2 4.6 5.2 {} {}}
+
+test scan-7.1 {string and character scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "abc defghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d
+} {4 abc def ghijk dum}
+test scan-7.2 {string and character scanning} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "a       bcdef" "%c%c%1s %s" a b c d] $a $b $c $d
+} {4 97 32 b cdef}
+test scan-7.3 {string and character scanning} {
+    set a {}; set b {}; set c {}
+    list [scan "123456 test " "%*c%*s %s %s %s" a b c] $a $b $c
+} {1 test {} {}}
+test scan-7.4 {string and character scanning} {
+    set a {}; set b {}; set c {}; set d
+    list [scan "ababcd01234  f 123450" {%4[abcd] %4[abcd] %[^abcdef] %[^0]} a b c d] $a $b $c $d
+} {4 abab cd {01234  } {f 12345}}
+test scan-7.5 {string and character scanning} {
+    set a {}; set b {}; set c {}
+    list [scan "aaaaaabc aaabcdefg  + +  XYZQR" {%*4[a] %s %*4[a]%s%*4[ +]%c} a b c] $a $b $c
+} {3 aabc bcdefg 43}
+test scan-7.6 {string and character scanning, unicode} utf8 {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "abc d\u00c7fghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d
+} "4 abc d\u00c7f ghijk dum"
+test scan-7.7 {string and character scanning, unicode} utf8 {
+    set a {}; set b {}
+    list [scan "ab\u00c7cdef" "ab%c%c" a b] $a $b
+} "2 199 99"
+test scan-7.8 {string and character scanning, unicode} utf8 {
+    set a {}; set b {}
+    list [scan "ab\ufeffdef" "%\[ab\ufeff\]" a] $a
+} "1 ab\ufeff"
+test scan-8.1 {error conditions} {
+    catch {scan a}
+} 1
+test scan-8.2 {error conditions} jim {
+    catch {scan a} msg
+    set msg
+} {wrong # args: should be "scan string format ?varName varName ...?"}
+test scan-8.3 {error conditions} jim {
+    list [catch {scan a %D x} msg] $msg
+} {1 {bad scan conversion character}}
+test scan-8.4 {error conditions} jim {
+    list [catch {scan a %O x} msg] $msg
+} {1 {bad scan conversion character}}
+test scan-8.5 {error conditions} jim {
+    list [catch {scan a %X x} msg] $msg
+} {1 {bad scan conversion character}}
+test scan-8.6 {error conditions} jim {
+    list [catch {scan a %F x} msg] $msg
+} {1 {bad scan conversion character}}
+test scan-8.7 {error conditions} jim {
+    list [catch {scan a %E x} msg] $msg
+} {1 {bad scan conversion character}}
+test scan-8.8 {error conditions} {
+    list [catch {scan a "%d %d" a} msg] $msg
+} {1 {different numbers of variable names and field specifiers}}
+test scan-8.9 {error conditions} {
+    list [catch {scan a "%d %d" a b c} msg] $msg
+} {1 {variable is not assigned by any conversion specifiers}}
+test scan-8.10 {error conditions} {
+    set a {}; set b {}; set c {}; set d {}
+    list [expr {[scan "  a" " a %d %d %d %d" a b c d] <= 0}] $a $b $c $d
+} {1 {} {} {} {}}
+test scan-8.11 {error conditions} {
+    set a {}; set b {}; set c {}; set d {}
+    list [scan "1 2" "%d %d %d %d" a b c d] $a $b $c $d
+} {2 1 2 {} {}}
+test scan-8.12 {error conditions} {
+    set a 44
+    list [catch {scan 44 %d a(0)} msg]
+} {1}
+test scan-8.13 {error conditions} {
+    set a 44
+    list [catch {scan 44 %c a(0)} msg]
+} {1}
+test scan-8.14 {error conditions} {
+    set a 44
+    list [catch {scan 44 %s a(0)} msg]
+} {1}
+test scan-8.15 {error conditions} {
+    set a 44
+    list [catch {scan 44 %f a(0)} msg]
+} {1}
+
+
+
+
+catch {unset a}
+test scan-8.17 {error conditions} {
+    list [catch {scan 44 %2c a} msg] $msg
+} {1 {field width may not be specified in %c conversion}}
+test scan-8.18 {error conditions} {
+    list [catch {scan abc {%[} x} msg] $msg
+} {1 {unmatched [ in format string}}
+test scan-8.19 {error conditions} {
+    list [catch {scan abc {%[^a} x} msg] $msg
+} {1 {unmatched [ in format string}}
+test scan-8.20 {error conditions} {
+    list [catch {scan abc {%[^]a} x} msg] $msg
+} {1 {unmatched [ in format string}}
+test scan-8.21 {error conditions} {
+    list [catch {scan abc {%[]a} x} msg] $msg
+} {1 {unmatched [ in format string}}
+
+test scan-9.1 {lots of arguments} {
+    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20
+} 20
+test scan-9.2 {lots of arguments} {
+    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20
+    set a20
+} 200
+
+test scan-10.1 {miscellaneous tests} {
+    set a {}
+    list [scan ab16c ab%dc a] $a
+} {1 16}
+test scan-10.2 {miscellaneous tests} {
+    set a {}
+    list [scan ax16c ab%dc a] $a
+} {0 {}}
+test scan-10.3 {miscellaneous tests} {
+    set a {}
+    list [catch {scan ab%c114 ab%%c%d a} msg] $msg $a
+} {0 1 114}
+test scan-10.4 {miscellaneous tests} {
+    set a {}
+    list [catch {scan ab%c14 ab%%c%d a} msg] $msg $a
+} {0 1 14}
+test scan-10.5 {miscellaneous tests} {
+    catch {unset arr}
+    set arr(2) {}
+    list [catch {scan ab%c14 ab%%c%d arr(2)} msg] $msg $arr(2)
+} {0 1 14}
+
+test scan-11.1 {alignment in results array (TCL_ALIGN)} {
+    scan "123 13.6" "%s %f" a b
+    set b
+} 13.6
+test scan-11.2 {alignment in results array (TCL_ALIGN)} {
+    scan "1234567 13.6" "%s %f" a b
+    set b
+} 13.6
+test scan-11.3 {alignment in results array (TCL_ALIGN)} {
+    scan "12345678901 13.6" "%s %f" a b
+    set b
+} 13.6
+test scan-11.4 {alignment in results array (TCL_ALIGN)} {
+    scan "123456789012345 13.6" "%s %f" a b
+    set b
+} 13.6
+test scan-11.5 {alignment in results array (TCL_ALIGN)} {
+    scan "1234567890123456789 13.6" "%s %f" a b
+    set b
+} 13.6
+
+test scan-12.1 {Tcl_ScanObjCmd, inline case} {
+    scan a %c
+} 97
+test scan-12.2 {Tcl_ScanObjCmd, inline case} {
+    scan abc %c%c%c%c
+} {97 98 99 {}}
+test scan-12.3 {Tcl_ScanObjCmd, inline case} {
+    scan abc %s%c
+} {abc {}}
+test scan-12.4 {Tcl_ScanObjCmd, inline case, underflow} {
+    scan abc abc%c
+} {}
+test scan-12.5 {Tcl_ScanObjCmd, inline case} {
+    scan abc bogus%c%c%c
+} {{} {} {}}
+test scan-12.6 {Tcl_ScanObjCmd, inline case} {
+    # degenerate case, behavior changed from 8.2 to 8.3
+    list [catch {scan foo foobar} msg] $msg
+} {0 {}}
+test scan-12.7 {Tcl_ScanObjCmd, inline case lots of arguments} {
+    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140\
+           150 160 170 180 190 200" \
+           "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"
+} {10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 {}}
+
+test scan-13.1 {Tcl_ScanObjCmd, inline XPG case} {
+    scan a {%1$c}
+} 97
+test scan-13.2 {Tcl_ScanObjCmd, inline XPG case} {
+    scan abc {%1$c%2$c%3$c%4$c}
+} {97 98 99 {}}
+test scan-13.3 {Tcl_ScanObjCmd, inline XPG case} {
+    list [catch {scan abc {%1$c%1$c}} msg] $msg
+} {1 {variable is assigned by multiple "%n$" conversion specifiers}}
+test scan-13.4 {Tcl_ScanObjCmd, inline XPG case} {
+    scan abc {%2$s%1$c}
+} {{} abc}
+test scan-13.5 {Tcl_ScanObjCmd, inline XPG case, underflow} {
+    scan abc {abc%5$c}
+} {}
+test scan-13.6 {Tcl_ScanObjCmd, inline XPG case} {
+    catch {scan abc {bogus%1$c%5$c%10$c}} msg
+    list [llength $msg] $msg
+} {10 {{} {} {} {} {} {} {} {} {} {}}}
+test scan-13.7 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
+    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" {%20$d %18$d %17$d %16$d %15$d %14$d %13$d %12$d %11$d %10$d %9$d %8$d %7$d %6$d %5$d %4$d %3$d %2$d %1$d}
+} {190 180 170 160 150 140 130 120 110 100 90 80 70 60 50 40 30 20 {} 10}
+test scan-13.8 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
+    set msg [scan "10 20 30" {%100$d %5$d %200$d}]
+    list [llength $msg] [lindex $msg 99] [lindex $msg 4] [lindex $msg 199]
+} {200 10 20 30}
+
+test scan-14.1 {scan with null chars} {
+    scan a\0c %c%c%c
+} {97 0 99}
+
+test scan-14.2 {scan with null chars} {
+    scan \0\0c %c%c%c
+} {0 0 99}
+
+test scan-14.3 {scan with null chars} {
+    scan ab12x\0 %cb%dx%c
+} {97 12 0}
+
+testreport
diff --git a/jim/tests/signal.test b/jim/tests/signal.test
new file mode 100755 (executable)
index 0000000..e212501
--- /dev/null
@@ -0,0 +1,98 @@
+source [file dirname [info script]]/testing.tcl
+
+needs cmd signal
+needs cmd pid
+testConstraint try [expr {[info commands try] ne ""}]
+
+test signal-1.1 "catch/throw" {
+       signal handle TERM
+       set x 1
+       set rc [catch -signal {
+               signal throw -TERM
+               incr x
+       } result]
+       signal default TERM
+       list [info returncode $rc] $result $x
+} {signal SIGTERM 1}
+
+test signal-1.2 "catch/kill" {
+       signal handle TERM
+       set x 1
+       set rc [catch -signal {
+               kill -TERM [pid]
+               incr x
+       } result]
+       signal default TERM
+       list [info returncode $rc] $result $x
+} {signal SIGTERM 1}
+
+test signal-1.3 "catch/alarm" {
+       signal handle ALRM
+       set x 1
+       set rc [catch -signal {
+               alarm .2
+               sleep 1
+               incr x
+       } result]
+       signal default ALRM
+       list [info returncode $rc] $result $x
+} {signal SIGALRM 1}
+
+test signal-1.4 "multiple signals before catch" {
+       signal handle ALRM INT
+       kill -INT [pid]
+       alarm .2
+       sleep 1
+       set x 1
+       set rc [catch -signal {
+               # Doesn't not execute because signals already active
+               incr x
+       } result]
+       signal default ALRM INT
+       list [info returncode $rc] [lsort $result] $x
+} {signal {SIGALRM SIGINT} 1}
+
+test signal-1.5 "ignored signals" {
+       signal handle INT
+       signal ignore HUP
+
+       set x 1
+       catch -signal {
+               # Send an ignored signal
+               kill -HUP [pid]
+               incr x
+               # Now a caught signal
+               kill -INT [pid]
+               incr x
+       } result
+       signal default INT TERM
+       list [lsort $result] $x
+} {SIGINT 2}
+
+test signal-1.6 "check ignored signals" {
+       list [signal check SIGINT] [signal check]
+} {{} SIGHUP}
+
+test signal-1.7 "clearing ignored signals" {
+       signal check -clear
+       signal check
+} {}
+
+test signal-1.8 "try/signal" try {
+       signal handle ALRM
+       try -signal {
+               alarm 0.4
+               foreach i [range 10] {
+                       sleep 0.1
+               }
+               set msg ""
+       } on signal {msg} {
+               # Just set msg here
+       } finally {
+               alarm 0
+       }
+       signal default ALRM
+       list [expr {$i in {3 4 5}}] $msg
+} {1 SIGALRM}
+
+testreport
diff --git a/jim/tests/stacktrace.test b/jim/tests/stacktrace.test
new file mode 100755 (executable)
index 0000000..13028a9
--- /dev/null
@@ -0,0 +1,117 @@
+source [file dirname [info script]]/testing.tcl
+needs constraint jim; needs cmd package
+package require errors
+# Make this a proc so that the line numbers don't have to change
+proc main {} {
+       set id1 0
+       foreach type {badcmd badvar error interpbadvar interpbadcmd package source badpackage returncode} {
+               set id2 0
+               incr id1
+               foreach method {call uplevel eval evalstr} {
+                       incr id2
+                       set exp ""
+                       if {[info exists ::expected(err-$id1.$id2)]} {
+                               set exp $::expected(err-$id1.$id2)
+                       }
+                       test err-$id1.$id2 "Stacktrace on error type $type, method $method" {
+                               set rc [catch {error_caller $type $method} msg]
+                               #puts "\n-----------------\n$type, $method\n[errorInfo $msg]\n\n"
+                               if {$::SHOW_EXPECTED} { puts stderr "\terr-$id1.$id2 {[list $rc $msg [info stacktrace]]}" }
+
+                               list $rc $msg [info stacktrace]
+                       } $exp
+               }
+       }
+       proc unknown {args} {
+               error "from unknown"
+       }
+
+       test err-10.1 "Stacktrace on error from unknown (badcmd, call)" {
+               set rc [catch {error_caller badcmd call} msg]
+               #puts stderr "err-10.1\n[errorInfo $msg]\n"
+               #puts stderr "\terr-10.1 {[list $rc $msg [info stacktrace]]}"
+
+               list $rc $msg [info stacktrace]
+       } {1 {from unknown} {{} stacktrace.test 26 {} errors.tcl 6 error_generator errors.tcl 44 error_caller stacktrace.test 30}}
+
+       rename unknown ""
+
+       set a {one}
+       set b [list 1 \
+               2 \
+               3]
+       set c {two}
+       set d "list 1 
+               2 
+               3"
+       set e {three}
+       set f "list 1  \
+               2  \
+               3"
+       set g {four}
+
+       test source-1.1 "Basic line numbers" {
+               info source $a
+       } {stacktrace.test 39}
+
+       test source-1.2 "Line numbers after command with escaped newlines" {
+               info source $c
+       } {stacktrace.test 43}
+       test source-1.3 "Line numbers after string with newlines" {
+               info source $e
+       } {stacktrace.test 47}
+       test source-1.4 "Line numbers after string with escaped newlines" {
+               info source $g
+       } {stacktrace.test 51}
+}
+
+set expected {
+       err-1.1 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-1.2 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-1.3 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-1.4 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-2.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-2.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-2.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-2.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-3.1 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-3.2 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-3.3 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-3.4 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-4.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-4.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-4.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-4.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-5.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-5.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-5.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-5.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-6.1 {1 {from dummyproc
+Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-6.2 {1 {from dummyproc
+Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-6.3 {1 {from dummyproc
+Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-6.4 {1 {from dummyproc
+Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-7.1 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-7.2 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-7.3 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-7.4 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-8.1 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 44 error_caller stacktrace.test 17}}
+       err-8.2 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 47 error_caller stacktrace.test 17}}
+       err-8.3 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 50 error_caller stacktrace.test 17}}
+       err-8.4 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 53 error_caller stacktrace.test 17}}
+       err-9.1 {1 failure {{} errors.tcl 44 error_caller stacktrace.test 17}}
+       err-9.2 {1 failure {{} errors.tcl 47 error_caller stacktrace.test 17}}
+       err-9.3 {1 failure {{} errors.tcl 50 error_caller stacktrace.test 17}}
+       err-9.4 {1 failure {{} errors.tcl 53 error_caller stacktrace.test 17}}
+}
+
+# Set this to output expected results to stderr
+# in a form which can be pasted into 'expected' below
+set SHOW_EXPECTED 0
+
+main
+
+testreport
diff --git a/jim/tests/string.test b/jim/tests/string.test
new file mode 100755 (executable)
index 0000000..650088c
--- /dev/null
@@ -0,0 +1,910 @@
+# Commands covered:  string
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: string.test,v 1.23.2.1 2001/04/03 22:54:38 hobbs Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+# Some tests require the testobj command
+
+test string-1.1 {error conditions} {
+    list [catch {string gorp a b} msg]
+} {1}
+test string-1.2 {error conditions} {
+    list [catch {string} msg]
+} {1}
+
+test string-2.1 {string compare, too few args} {
+    list [catch {string compare a} msg]
+} {1}
+test string-2.2 {string compare, bad args} {
+    list [catch {string compare a b c} msg]
+} {1}
+test string-2.3 {string compare, bad args} {
+    list [catch {string compare -length -nocase str1 str2} msg]
+} {1}
+test string-2.4 {string compare, too many args} {
+    list [catch {string compare -length 10 -nocase str1 str2 str3} msg]
+} {1}
+test string-2.5 {string compare with length unspecified} {
+    list [catch {string compare -length 10 10} msg]
+} {1}
+test string-2.6 {string compare} {
+    string compare abcde abdef
+} -1
+test string-2.7 {string compare, shortest method name} {
+    string c abcde ABCDE
+} 1
+test string-2.8 {string compare} {
+    string compare abcde abcde
+} 0
+test string-2.9 {string compare with length} {
+    string compare -length 2 abcde abxyz
+} 0
+test string-2.10 {string compare with special index} {
+    list [catch {string compare -length end-3 abcde abxyz} msg]
+} {1}
+test string-2.12 {string compare, high bit} {
+    # This test will fail if the underlying comparaison
+    # is using signed chars instead of unsigned chars.
+    # (like SunOS's default memcmp thus the compat/memcmp.c)
+    string compare "\x80" "@"
+    # Nb this tests works also in utf8 space because \x80 is
+    # translated into a 2 or more bytelength but whose first byte has
+    # the high bit set.
+} 1
+test string-2.13 {string compare -nocase} {
+    string compare -nocase abcde abdef
+} -1
+test string-2.14 {string compare -nocase} {
+    string c -nocase abcde ABCDE
+} 0
+test string-2.15 {string compare -nocase} {
+    string compare -nocase abcde abcde
+} 0
+test string-2.16 {string compare -nocase with length} {
+    string compare -length 2 -nocase abcde Abxyz
+} 0
+test string-2.17 {string compare -nocase with length} {
+    string compare -nocase -length 3 abcde Abxyz
+} -1
+test string-2.18 {string compare -nocase with length <= 0} {
+    string compare -nocase -length -1 abcde AbCdEf
+} -1
+test string-2.19 {string compare -nocase with excessive length} {
+    string compare -nocase -length 50 AbCdEf abcde
+} 1
+test string-2.20 {string compare -len unicode} {
+    # These are strings that are 6 BYTELENGTH long, but the length
+    # shouldn't make a different because there are actually 3 CHARS long
+    string compare -len 5 \334\334\334 \334\334\374
+} -1
+test string-2.21 {string compare -nocase with special index} {
+    list [catch {string compare -nocase -length end-3 Abcde abxyz} msg]
+} {1}
+test string-2.22 {string compare, null strings} {
+    string compare "" ""
+} 0
+test string-2.23 {string compare, null strings} {
+    string compare "" foo
+} -1
+test string-2.24 {string compare, null strings} {
+    string compare foo ""
+} 1
+test string-2.25 {string compare -nocase, null strings} {
+    string compare -nocase "" ""
+} 0
+test string-2.26 {string compare -nocase, null strings} {
+    string compare -nocase "" foo
+} -1
+test string-2.27 {string compare -nocase, null strings} {
+    string compare -nocase foo ""
+} 1
+test string-2.28 {string equal with length, unequal strings} {
+    string compare -length 2 abc abde
+} 0
+test string-2.29 {string equal with length, unequal strings} {
+    string compare -length 2 ab abde
+} 0
+# only need a few tests on equal, since it uses the same code as
+# string compare, but just modifies the return output
+test string-3.1 {string equal} {
+    string equal abcde abdef
+} 0
+test string-3.2 {string equal} {
+    string eq abcde ABCDE
+} 0
+test string-3.3 {string equal} {
+    string equal abcde abcde
+} 1
+test string-3.4 {string equal -nocase} utf8 {
+    string equal -nocase \u00dc\u00dc\u00dc\u00dc\u00fc\u00fc\u00fc\u00fc \u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc
+} 1
+test string-3.5 {string equal -nocase} {
+    string equal -nocase abcde abdef
+} 0
+test string-3.6 {string equal -nocase} {
+    string eq -nocase abcde ABCDE
+} 1
+test string-3.7 {string equal -nocase} {
+    string equal -nocase abcde abcde
+} 1
+test string-3.8 {string equal with length, unequal strings} {
+    string equal -length 2 abc abde
+} 1
+test string-4.1 {string first, too few args} {
+    list [catch {string first a} msg]
+} {1}
+test string-4.2 {string first, bad args} {
+    list [catch {string first a b c} msg]
+} {1}
+test string-4.3 {string first, too many args} {
+    list [catch {string first a b 5 d} msg]
+} {1}
+test string-4.4 {string first} {
+    string first bq abcdefgbcefgbqrs
+} 12
+test string-4.5 {string first} {
+    string fir bcd abcdefgbcefgbqrs
+} 1
+test string-4.6 {string first} {
+    string f b abcdefgbcefgbqrs
+} 1
+test string-4.7 {string first} {
+    string first xxx x123xx345xxx789xxx012
+} 9
+test string-4.8 {string first} {
+    string first "" x123xx345xxx789xxx012
+} -1
+test string-4.14 {string first, start index} {
+    string first a abcabc end-4
+} 3
+test string-4.15 {string first, empty needle} {
+    string first "" b
+} -1
+test string-4.16 {string first, empty haystack} {
+    string first a ""
+} -1
+test string-4.17 {string first, needle bigger than haystack} {
+    string first aaa b
+} -1
+test string-4.18 {string first, negative index} {
+    string first a aaa -4
+} 0
+test string-4.19 {string first, not found} {
+    string first a bcd
+} -1
+
+test string-5.1 {string index} {
+    list [catch {string index} msg]
+} {1}
+test string-5.2 {string index} {
+    list [catch {string index a b c} msg]
+} {1}
+test string-5.3 {string index} {
+    string index abcde 0
+} a
+test string-5.4 {string index} {
+    string in abcde 4
+} e
+test string-5.5 {string index} {
+    string index abcde 5
+} {}
+test string-5.6 {string index} {
+    list [catch {string index abcde -10} msg]
+} {0}
+test string-5.7 {string index} {
+    list [catch {string index a xyz} msg]
+} {1}
+test string-5.8 {string index} {
+    string index abc end
+} c
+test string-5.9 {string index} {
+    string index abc end-1
+} b
+test string-5.17 {string index, bad integer} tcl {
+    list [catch {string index "abc" 08} msg]
+} {1}
+test string-5.18 {string index, bad integer} tcl {
+    list [catch {string index "abc" end-00289} msg]
+} {1}
+test string-6.1 {string is, too few args} jim {
+    list [catch {string is} msg] $msg
+} {1 {wrong # args: should be "string is class ?-strict? str"}}
+test string-6.2 {string is, too few args} jim {
+    list [catch {string is alpha} msg] $msg
+} {1 {wrong # args: should be "string is class ?-strict? str"}}
+test string-6.3 {string is, bad args} jim {
+    list [catch {string is alpha -failin str} msg] $msg
+} {1 {wrong # args: should be "string is class ?-strict? str"}}
+test string-6.4 {string is, too many args} jim {
+    list [catch {string is alpha -failin var -strict str more} msg] $msg
+} {1 {wrong # args: should be "string is class ?-strict? str"}}
+test string-6.5 {string is, class check} jim {
+    list [catch {string is bogus str} msg] $msg
+} {1 {bad class "bogus": must be alnum, alpha, ascii, control, digit, double, graph, integer, lower, print, punct, space, upper, or xdigit}}
+test string-6.6 {string is, ambiguous class} jim {
+    list [catch {string is al str} msg] $msg
+} {1 {ambiguous class "al": must be alnum, alpha, ascii, control, digit, double, graph, integer, lower, print, punct, space, upper, or xdigit}}
+test string-6.10 {string is, ok on empty} {
+    string is alpha {}
+} 1
+test string-6.11 {string is, -strict check against empty} {
+    string is alpha -strict {}
+} 0
+test string-6.12 {string is alnum, true} {
+    string is alnum abc123
+} 1
+test string-6.15 {string is alpha, true} {
+    string is alpha abc
+} 1
+test string-6.16 {string is ascii, true} {
+    string is ascii abc123
+} 1
+test string-6.17 {string is ascii, false} {
+    string is ascii 0123Ãœ567
+} 0
+test string-6.24 {string is digit, true} {
+    string is digit 0123456789
+} 1
+test string-6.25 {string is digit, false} {
+    list [string is digit 0123Ãœ567]
+} {0}
+test string-6.26 {string is digit, false} {
+    list [string is digit +123567]
+} {0}
+test string-6.27 {string is double, true} {
+    string is double 1
+} 1
+test string-6.28 {string is double, true} {
+    string is double [expr double(1)]
+} 1
+test string-6.29 {string is double, true} {
+    string is double 1.0
+} 1
+test string-6.30 {string is double, true} {
+    string is double [string compare a a]
+} 1
+test string-6.31 {string is double, true} {
+    string is double "   +1.0e-1  "
+} 1
+test string-6.32 {string is double, true} {
+    string is double "\n1.0\v"
+} 1
+test string-6.33 {string is double, false} {
+    list [string is double  1abc]
+} {0}
+test string-6.34 {string is double, false} {
+    list [string is double  abc]
+} {0}
+test string-6.35 {string is double, false} {
+    list [string is double  "   1.0e4e4  "]
+} {0}
+test string-6.36 {string is double, false} {
+    list [string is double  "\n"]
+} {0}
+test string-6.38 {string is double, false on underflow} jim {
+    list [string is double  123e-9999]
+} {0}
+test string-6.39 {string is double, false} {
+    # This test is non-portable because IRIX thinks 
+    # that .e1 is a valid double - this is really a bug
+    # on IRIX as .e1 should NOT be a valid double
+
+    list [string is double  .e1]
+} {0}
+test string-6.48 {string is integer, true} {
+    string is integer +1234567890
+} 1
+test string-6.49 {string is integer, true on type} {
+    string is integer [expr int(50.0)]
+} 1
+test string-6.50 {string is integer, true} {
+    string is integer [list -10]
+} 1
+test string-6.51 {string is integer, true as hex} {
+    string is integer 0xabcdef
+} 1
+test string-6.52 {string is integer, true as octal} {
+    string is integer 012345
+} 1
+test string-6.53 {string is integer, true with whitespace} {
+    string is integer "  \n1234\v"
+} 1
+test string-6.54 {string is integer, false} {
+    list [string is integer  123abc]
+} 0
+test string-6.56 {string is integer, false} {
+    list [string is integer  [expr double(1)]]
+} 0
+test string-6.57 {string is integer, false} {
+    list [string is integer  "    "]
+} 0
+test string-6.58 {string is integer, false on bad octal} jim {
+    list [string is integer  036963]
+} 1
+test string-6.59 {string is integer, false on bad octal} tcl {
+    list [string is integer  036963]
+} 0
+test string-6.60 {string is integer, false on bad hex} {
+    list [string is integer  0X345XYZ]
+} 0
+test string-6.61 {string is lower, true} {
+    string is lower abc
+} 1
+test string-6.62 {string is lower, false} {
+    list [string is lower  aBc]
+} 0
+test string-6.63 {string is lower, false} {
+    list [string is lower  abc1]
+} 0
+test string-6.64 {string is lower, unicode false} {
+    list [string is lower  abÃœUE]
+} 0
+test string-6.65 {string is space, true} {
+    string is space " \t\n\v\f"
+} 1
+test string-6.66 {string is space, false} {
+    list [string is space  " \t\n\v1\f"]
+} 0
+test string-6.75 {string is upper, true} {
+    string is upper ABC
+} 1
+test string-6.77 {string is upper, false} {
+    list [string is upper  AbC]
+} 0
+test string-6.78 {string is upper, false} {
+    list [string is upper  AB2C]
+} 0
+test string-6.84 {string is control} {
+    ## Control chars are in the ranges
+    ## 00..1F && 7F..9F
+    list [string is control  \x00\x01\x10\x1F\x7F\x80\x9F\x60]
+} 0
+test string-6.85 {string is control} tcl {
+    string is control \u0100
+} 0
+test string-6.86 {string is graph} {
+    ## graph is any print char, except space
+    list [string is gra  "0123abc!@#\$ "]
+} 0
+test string-6.87 {string is print} {
+    ## basically any printable char
+    list [string is print  "0123abc!@#\$ \010"]
+} 0
+test string-6.88 {string is punct} {
+    ## any graph char that isn't alnum
+    list [string is punct  "_!@#\000beq0"]
+} 0
+test string-6.89 {string is xdigit} {
+    list [string is xdigit  0123456789\u0061bcdefABCDEFg]
+} 0
+
+test string-7.1 {string last, too few args} {
+    list [catch {string last a} msg]
+} {1}
+test string-7.2 {string last, bad args} {
+    list [catch {string last a b c} msg]
+} {1}
+test string-7.3 {string last, too many args} {
+    list [catch {string last a b c d} msg]
+} {1}
+test string-7.4 {string last} {
+    string la xxx xxxx123xx345x678
+} 1
+test string-7.5 {string last} {
+    string last xx xxxx123xx345x678
+} 7
+test string-7.6 {string last} {
+    string las x xxxx123xx345x678
+} 12
+test string-7.13 {string last, start index} {
+    ## Constrain to last 'a' should work
+    string last ba badbad end-1
+} 3
+test string-7.14 {string last, start index} {
+    ## Constrain to last 'b' should skip last 'ba'
+    string last ba badbad end-2
+} 0
+test string-7.15 {string last, start index} {
+    string last \u00dca \u00dcad\u00dcad 0
+} -1
+test string-7.16 {string last, start index} utf8 {
+    string last \u00dca \u00dcad\u00dcad end-1
+} 3
+test string-7.17 {string last, too few args} {
+    string last abc def
+} -1
+test string-9.1 {string length} {
+    list [catch {string length} msg]
+} {1}
+test string-9.2 {string length} {
+    list [catch {string length a b} msg]
+} {1}
+test string-9.3 {string length} {
+    string length "a little string"
+} 15
+test string-9.4 {string length} {
+    string le ""
+} 0
+
+test string-10.1 {string map, too few args} {
+    list [catch {string map} msg]
+} {1}
+test string-10.2 {string map, bad args} {
+    list [catch {string map {a b} abba oops} msg]
+} {1}
+test string-10.3 {string map, too many args} {
+    list [catch {string map -nocase {a b} str1 str2} msg]
+} {1}
+test string-10.4 {string map} {
+    string map {a b} abba
+} {bbbb}
+test string-10.5 {string map} {
+    string map {a b} a
+} {b}
+test string-10.6 {string map -nocase} {
+    string map -nocase {a b} Abba
+} {bbbb}
+test string-10.7 {string map} {
+    string map {abc 321 ab * a A} aabcabaababcab
+} {A321*A*321*}
+test string-10.8 {string map -nocase} {
+    string map -nocase {aBc 321 Ab * a A} aabcabaababcab
+} {A321*A*321*}
+test string-10.9 {string map -nocase} {
+    string map -no {abc 321 Ab * a A} aAbCaBaAbAbcAb
+} {A321*A*321*}
+test string-10.10 {string map} {
+    list [catch {string map {a b c} abba} msg]
+} {1}
+test string-10.11 {string map, nulls} {
+    string map {\x00 NULL blah \x00nix} {qwerty}
+} {qwerty}
+test string-10.12 {string map, unicode} {
+    string map [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU"
+} aueue\u00dc\0EU
+test string-10.13 {string map, -nocase unicode} {
+    string map -nocase [list \u00fc ue UE \u00dc] "a\u00fcueUE\000EU"
+} aue\u00dc\u00dc\0EU
+test string-10.14 {string map, -nocase null arguments} {
+    string map -nocase {{} abc} foo
+} foo
+test string-10.15 {string map, one pair case} {
+    string map -nocase {abc 32} aAbCaBaAbAbcAb
+} {a32aBaAb32Ab}
+test string-10.16 {string map, one pair case} {
+    string map -nocase {ab 4321} aAbCaBaAbAbcAb
+} {a4321C4321a43214321c4321}
+test string-10.17 {string map, one pair case} {
+    string map {Ab 4321} aAbCaBaAbAbcAb
+} {a4321CaBa43214321c4321}
+
+test string-11.1 {string match, too few args} {
+    list [catch {string match a} msg]
+} {1}
+test string-11.2 {string match, too many args} {
+    list [catch {string match a b c d} msg]
+} {1}
+test string-11.3 {string match} {
+    string match abc abc
+} 1
+test string-11.4 {string match} {
+    string mat abc abd
+} 0
+test string-11.5 {string match} {
+    string match ab*c abc
+} 1
+test string-11.6 {string match} {
+    string match ab**c abc
+} 1
+test string-11.7 {string match} {
+    string match ab* abcdef
+} 1
+test string-11.8 {string match} {
+    string match *c abc
+} 1
+test string-11.9 {string match} {
+    string match *3*6*9 0123456789
+} 1
+test string-11.10 {string match} {
+    string match *3*6*9 01234567890
+} 0
+test string-11.11 {string match} {
+    string match a?c abc
+} 1
+test string-11.12 {string match} {
+    string match a??c abc
+} 0
+test string-11.13 {string match} {
+    string match ?1??4???8? 0123456789
+} 1
+test string-11.14 {string match} {
+    string match {[abc]bc} abc
+} 1
+test string-11.15 {string match} {
+    string match {a[abc]c} abc
+} 1
+test string-11.16 {string match} {
+    string match {a[xyz]c} abc
+} 0
+test string-11.17 {string match} {
+    string match {12[2-7]45} 12345
+} 1
+test string-11.18 {string match} {
+    string match {12[ab2-4cd]45} 12345
+} 1
+test string-11.19 {string match} {
+    string match {12[ab2-4cd]45} 12b45
+} 1
+test string-11.20 {string match} {
+    string match {12[ab2-4cd]45} 12d45
+} 1
+test string-11.21 {string match} {
+    string match {12[ab2-4cd]45} 12145
+} 0
+test string-11.22 {string match} {
+    string match {12[ab2-4cd]45} 12545
+} 0
+test string-11.23 {string match} {
+    string match {a\*b} a*b
+} 1
+test string-11.24 {string match} {
+    string match {a\*b} ab
+} 0
+test string-11.25 {string match} {
+    string match {a\*\?\[\]\\\x} "a*?\[\]\\x"
+} 1
+test string-11.26 {string match} {
+    string match ** ""
+} 1
+test string-11.27 {string match} {
+    string match *. ""
+} 0
+test string-11.28 {string match} {
+    string match "" ""
+} 1
+test string-11.29 {string match} {
+    string match \[a a
+} 1
+test string-11.30 {string match, bad args} {
+    list [catch {string match - b c} msg]
+} {1}
+test string-11.31 {string match case} {
+    string match a A
+} 0
+test string-11.32 {string match nocase} {
+    string match -nocase a A
+} 1
+test string-11.34 {string match nocase} {
+    string match -nocase a*f ABCDEf
+} 1
+test string-11.35 {string match case, false hope} {
+    # This is true because '_' lies between the A-Z and a-z ranges
+    string match {[A-z]} _
+} 1
+test string-11.36 {string match nocase range} {
+    # This is false because although '_' lies between the A-Z and a-z ranges,
+    # we lower case the end points before checking the ranges.
+    string match -nocase {[A-z]} _
+} 0
+test string-11.37 {string match nocase} {
+    string match -nocase {[A-fh-Z]} g
+} 0
+test string-11.38 {string match case, reverse range} {
+    string match {[A-fh-Z]} g
+} 1
+test string-11.39 {string match, *\ case} {
+    string match {*\abc} abc
+} 1
+test string-11.40 {string match, *special case} {
+    string match {*[ab]} abc
+} 0
+test string-11.41 {string match, *special case} {
+    string match {*[ab]*} abc
+} 1
+# I don't see why this shouldn't match. Ignored for jim
+test string-11.42 {string match, *special case} tcl {
+    string match "*\\" "\\"
+} 0
+test string-11.43 {string match, *special case} {
+    string match "*\\\\" "\\"
+} 1
+test string-11.44 {string match, *special case} {
+    string match "*???" "12345"
+} 1
+test string-11.45 {string match, *special case} {
+    string match "*???" "12"
+} 0
+test string-11.46 {string match, *special case} {
+    string match "*\\*" "abc*"
+} 1
+test string-11.47 {string match, *special case} {
+    string match "*\\*" "*"
+} 1
+test string-11.48 {string match, *special case} {
+    string match "*\\*" "*abc"
+} 0
+test string-11.49 {string match, *special case} {
+    string match "?\\*" "a*"
+} 1
+# I don't see why this shouldn't match. Ignored for jim
+test string-11.50 {string match, *special case} tcl {
+    string match "\\" "\\"
+} 0
+
+
+test string-12.1 {string range} {
+    list [catch {string range} msg]
+} {1}
+test string-12.2 {string range} {
+    list [catch {string range a 1} msg]
+} {1}
+test string-12.3 {string range} {
+    list [catch {string range a 1 2 3} msg]
+} {1}
+test string-12.4 {string range} {
+    string range abcdefghijklmnop 2 14
+} {cdefghijklmno}
+test string-12.5 {string range, last > length} {
+    string range abcdefghijklmnop 7 1000
+} {hijklmnop}
+test string-12.6 {string range} {
+    string range abcdefghijklmnop 10 end
+} {klmnop}
+test string-12.7 {string range, last < first} {
+    string range abcdefghijklmnop 10 9
+} {}
+test string-12.8 {string range, first < 0} {
+    string range abcdefghijklmnop -3 2
+} {abc}
+test string-12.9 {string range} {
+    string range abcdefghijklmnop -3 -2
+} {}
+test string-12.10 {string range} {
+    string range abcdefghijklmnop 1000 1010
+} {}
+test string-12.11 {string range} {
+    string range abcdefghijklmnop -100 end
+} {abcdefghijklmnop}
+test string-12.12 {string range} {
+    list [catch {string range abc abc 1} msg]
+} {1}
+test string-12.13 {string range} {
+    list [catch {string range abc 1 eof} msg]
+} {1}
+test string-12.14 {string range} {
+    string range abcdefghijklmnop end-1 end
+} {op}
+test string-12.15 {string range} {
+    string range abcdefghijklmnop end 1000
+} {p}
+test string-12.16 {string range} {
+    string range abcdefghijklmnop end end-1
+} {}
+
+test string-13.1 {string repeat} {
+    list [catch {string repeat} msg]
+} {1}
+test string-13.2 {string repeat} {
+    list [catch {string repeat abc 10 oops} msg]
+} {1}
+test string-13.3 {string repeat} {
+    string repeat {} 100
+} {}
+test string-13.4 {string repeat} {
+    string repeat { } 5
+} {     }
+test string-13.5 {string repeat} {
+    string repeat abc 3
+} {abcabcabc}
+test string-13.6 {string repeat} {
+    string repeat abc -1
+} {}
+test string-13.7 {string repeat} {
+    list [catch {string repeat abc end} msg]
+} {1}
+test string-13.8 {string repeat} {
+    string repeat {} -1000
+} {}
+test string-13.9 {string repeat} {
+    string repeat {} 0
+} {}
+test string-13.10 {string repeat} {
+    string repeat def 0
+} {}
+test string-13.11 {string repeat} {
+    string repeat def 1
+} def
+test string-13.12 {string repeat} {
+    string repeat ab\u7266cd 3
+} ab\u7266cdab\u7266cdab\u7266cd
+test string-13.13 {string repeat} {
+    string repeat \x00 3
+} \x00\x00\x00
+
+test string-14.1 {string replace} {
+    list [catch {string replace} msg] $msg
+} {1 {wrong # args: should be "string replace string first last ?string?"}}
+test string-14.2 {string replace} {
+    list [catch {string replace a 1} msg] $msg
+} {1 {wrong # args: should be "string replace string first last ?string?"}}
+test string-14.3 {string replace} {
+    list [catch {string replace a 1 2 3 4} msg] $msg
+} {1 {wrong # args: should be "string replace string first last ?string?"}}
+test string-14.4 {string replace} {
+} {}
+test string-14.5 {string replace} {
+    string replace abcdefghijklmnop 2 14
+} {abp}
+test string-14.6 {string replace} {
+    string replace abcdefghijklmnop 7 1000
+} {abcdefg}
+test string-14.7 {string replace} {
+    string replace abcdefghijklmnop 10 end
+} {abcdefghij}
+test string-14.8 {string replace} {
+    string replace abcdefghijklmnop 10 9
+} {abcdefghijklmnop}
+test string-14.9 {string replace} {
+    string replace abcdefghijklmnop -3 2
+} {defghijklmnop}
+test string-14.10 {string replace} {
+    string replace abcdefghijklmnop -3 -2
+} {abcdefghijklmnop}
+test string-14.11 {string replace} {
+    string replace abcdefghijklmnop 1000 1010
+} {abcdefghijklmnop}
+test string-14.12 {string replace} {
+    string replace abcdefghijklmnop -100 end
+} {}
+test string-14.13 {string replace} {
+    list [catch {string replace abc abc 1} msg] $msg
+} {1 {bad index "abc": must be integer?[+-]integer? or end?[+-]integer?}}
+test string-14.14 {string replace} {
+    list [catch {string replace abc 1 eof} msg] $msg
+} {1 {bad index "eof": must be integer?[+-]integer? or end?[+-]integer?}}
+test string-14.15 {string replace} {
+    string replace abcdefghijklmnop end-10 end-2 NEW
+} {abcdeNEWop}
+test string-14.16 {string replace} {
+    string replace abcdefghijklmnop 0 end foo
+} {foo}
+test string-14.17 {string replace} {
+    string replace abcdefghijklmnop end end-1
+} {abcdefghijklmnop}
+
+test string-15.1 {string tolower too few args} {
+    list [catch {string tolower} msg]
+} {1}
+test string-15.2 {string tolower bad args} {
+    list [catch {string tolower a b} msg]
+} {1}
+test string-15.3 {string tolower too many args} {
+    list [catch {string tolower ABC 1 end oops} msg]
+} {1}
+test string-15.4 {string tolower} {
+    string tolower ABCDeF
+} {abcdef}
+test string-15.5 {string tolower} {
+    string tolower "ABC  XyZ"
+} {abc  xyz}
+test string-15.6 {string tolower} {
+    string tolower {123#$&*()}
+} {123#$&*()}
+
+test string-16.1 {string toupper} {
+    list [catch {string toupper} msg]
+} {1}
+test string-16.2 {string toupper} {
+    list [catch {string toupper a b} msg]
+} {1}
+test string-16.4 {string toupper} {
+    string toupper abCDEf
+} {ABCDEF}
+test string-16.5 {string toupper} {
+    string toupper "abc xYz"
+} {ABC XYZ}
+test string-16.6 {string toupper} {
+    string toupper {123#$&*()}
+} {123#$&*()}
+
+test string-17.1 {string totitle} -body {
+    string totitle
+}  -returnCodes error -match glob -result {wrong # args: should be "string totitle string*}
+test string-17.3 {string totitle} {
+    string totitle abCDEf
+} {Abcdef}
+test string-17.4 {string totitle} {
+    string totitle "abc xYz"
+} {Abc xyz}
+test string-17.5 {string totitle} {
+    string totitle {123#$&*()}
+} {123#$&*()}
+
+test string-18.1 {string trim} {
+    list [catch {string trim} msg]
+} {1}
+test string-18.2 {string trim} {
+    list [catch {string trim a b c} msg]
+} {1}
+test string-18.3 {string trim} {
+    string trim "    XYZ      "
+} {XYZ}
+test string-18.4 {string trim} {
+    string trim "\t\nXYZ\t\n\r\n"
+} {XYZ}
+test string-18.5 {string trim} {
+    string trim "  A XYZ A    "
+} {A XYZ A}
+test string-18.6 {string trim} {
+    string trim "XXYYZZABC XXYYZZ" ZYX
+} {ABC }
+test string-18.7 {string trim} {
+    string trim "    \t\r      "
+} {}
+test string-18.8 {string trim} {
+    string trim {abcdefg} {}
+} {abcdefg}
+test string-18.9 {string trim} {
+    string trim {}
+} {}
+test string-18.10 {string trim} {
+    string trim ABC DEF
+} {ABC}
+test string-18.11 {string trim, unicode} {
+    string trim "\xe7\xe8 AB\xe7C \xe8\xe7" \xe7\xe8
+} " AB\xe7C "
+
+test string-19.1 {string trimleft} {
+    list [catch {string trimleft} msg]
+} {1}
+test string-19.2 {string trimleft} {
+    string trimleft "    XYZ      "
+} {XYZ      }
+
+test string-20.1 {string trimright errors} {
+    list [catch {string trimright} msg]
+} {1}
+test string-20.2 {string trimright errors} {
+    list [catch {string trimg a} msg]
+} {1}
+test string-20.3 {string trimright} {
+    string trimright "    XYZ      "
+} {    XYZ}
+test string-20.4 {string trimright} {
+    string trimright "   "
+} {}
+test string-20.5 {string trimright} {
+    string trimright ""
+} {}
+
+# Test for 8-bit clean and utf-8 trim chars
+test string-21.1 {string trim embedded nulls} {
+    string trim " abc\x00def "
+} "abc\x00def"
+test string-21.2 {string trimleft embedded nulls} {
+    string trimleft " abc\x00def "
+} "abc\x00def "
+test string-21.3 {string trimright embedded nulls} {
+    string trimright " abc\x00def "
+} " abc\x00def"
+test string-21.4 {string trim utf-8} {
+    string trim "\u00b5\u00b6abc\x00def\u00b5\u00b5" "\u00b5\u00b6"
+} "abc\x00def"
+
+test string-22.1 {string replace} {
+    string replace //test.net/path/path2?query=url?otherquery 21 end
+} {//test.net/path/path2}
+
+testreport
diff --git a/jim/tests/stringmatch.test b/jim/tests/stringmatch.test
new file mode 100755 (executable)
index 0000000..7fe3fcc
--- /dev/null
@@ -0,0 +1,225 @@
+# This file is a Tcl script to test the code in the file tclUtil.c.
+# This file is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1995-1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: util.test,v 1.7.2.1 2001/07/16 23:14:13 hobbs Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+test stringmatch-5.1 {Tcl_StringMatch} {
+    string match ab*c abc
+} 1
+test stringmatch-5.2 {Tcl_StringMatch} {
+    string match ab**c abc
+} 1
+test stringmatch-5.3 {Tcl_StringMatch} {
+    string match ab* abcdef
+} 1
+test stringmatch-5.4 {Tcl_StringMatch} {
+    string match *c abc
+} 1
+test stringmatch-5.5 {Tcl_StringMatch} {
+    string match *3*6*9 0123456789
+} 1
+test stringmatch-5.6 {Tcl_StringMatch} {
+    string match *3*6*9 01234567890
+} 0
+test stringmatch-5.7 {Tcl_StringMatch: UTF-8} {
+    string match *u \u4e4fu
+} 1
+test stringmatch-5.8 {Tcl_StringMatch} {
+    string match a?c abc
+} 1
+test stringmatch-5.9 {Tcl_StringMatch: UTF-8} utf8 {
+    # skip one character in string
+
+    string match a?c a\u4e4fc
+} 1
+test stringmatch-5.10 {Tcl_StringMatch} {
+    string match a??c abc
+} 0
+test stringmatch-5.11 {Tcl_StringMatch} {
+    string match ?1??4???8? 0123456789
+} 1
+test stringmatch-5.12 {Tcl_StringMatch} {
+    string match {[abc]bc} abc
+} 1
+test stringmatch-5.13 {Tcl_StringMatch: UTF-8} utf8 {
+    # string += Tcl_UtfToUniChar(string, &ch);
+
+    string match "\[\u4e4fxy\]bc" "\u4e4fbc"
+} 1
+test stringmatch-5.14 {Tcl_StringMatch} {
+    # if ((*pattern == ']') || (*pattern == '\0'))
+    # badly formed pattern
+
+    string match {[]} {[]}
+} 0
+test stringmatch-5.15 {Tcl_StringMatch} {
+    # if ((*pattern == ']') || (*pattern == '\0'))
+    # badly formed pattern
+
+    string match {[} {[}
+} 0
+test stringmatch-5.16 {Tcl_StringMatch} {
+    string match {a[abc]c} abc
+} 1
+test stringmatch-5.17 {Tcl_StringMatch: UTF-8} utf8 {
+    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
+    # get 1 UTF-8 character
+
+    string match "a\[a\u4e4fc]c" "a\u4e4fc"
+} 1
+test stringmatch-5.18 {Tcl_StringMatch: UTF-8} {
+    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
+    # proper advance: wrong answer would match on UTF trail byte of \u4e4f
+
+    string match {a[a\u4e4fc]c} a\u008fc
+} 0
+test stringmatch-5.19 {Tcl_StringMatch: UTF-8} {
+    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
+    # proper advance.
+
+    string match {a[a\u4e4fc]c} "acc"
+} 1
+test stringmatch-5.20 {Tcl_StringMatch} {
+    string match {a[xyz]c} abc
+} 0
+test stringmatch-5.21 {Tcl_StringMatch} {
+    string match {12[2-7]45} 12345
+} 1
+test stringmatch-5.22 {Tcl_StringMatch: UTF-8 range} {
+    string match "\[\u4e00-\u4e4f]" "0"
+} 0
+test stringmatch-5.23 {Tcl_StringMatch: UTF-8 range} utf8 {
+    string match "\[\u4e00-\u4e4f]" "\u4e33"
+} 1
+test stringmatch-5.24 {Tcl_StringMatch: UTF-8 range} utf8 {
+    string match "\[\u4e00-\u4e4f]" "\uff08"
+} 0
+test stringmatch-5.25 {Tcl_StringMatch} {
+    string match {12[ab2-4cd]45} 12345
+} 1
+test stringmatch-5.26 {Tcl_StringMatch} {
+    string match {12[ab2-4cd]45} 12b45
+} 1
+test stringmatch-5.27 {Tcl_StringMatch} {
+    string match {12[ab2-4cd]45} 12d45
+} 1
+test stringmatch-5.28 {Tcl_StringMatch} {
+    string match {12[ab2-4cd]45} 12145
+} 0
+test stringmatch-5.29 {Tcl_StringMatch} {
+    string match {12[ab2-4cd]45} 12545
+} 0
+test stringmatch-5.30 {Tcl_StringMatch: forwards range} {
+    string match {[k-w]} "z"
+} 0
+test stringmatch-5.31 {Tcl_StringMatch: forwards range} {
+    string match {[k-w]} "w"
+} 1
+test stringmatch-5.32 {Tcl_StringMatch: forwards range} {
+    string match {[k-w]} "r"
+} 1
+test stringmatch-5.33 {Tcl_StringMatch: forwards range} {
+    string match {[k-w]} "k"
+} 1
+test stringmatch-5.34 {Tcl_StringMatch: forwards range} {
+    string match {[k-w]} "a"
+} 0
+test stringmatch-5.35 {Tcl_StringMatch: reverse range} {
+    string match {[w-k]} "z"
+} 0
+test stringmatch-5.36 {Tcl_StringMatch: reverse range} {
+    string match {[w-k]} "w"
+} 1
+test stringmatch-5.37 {Tcl_StringMatch: reverse range} {
+    string match {[w-k]} "r"
+} 1
+test stringmatch-5.38 {Tcl_StringMatch: reverse range} {
+    string match {[w-k]} "k"
+} 1
+test stringmatch-5.39 {Tcl_StringMatch: reverse range} {
+    string match {[w-k]} "a"
+} 0
+test stringmatch-5.40 {Tcl_StringMatch: skip correct number of ']'} {
+    string match {[A-]x} Ax
+} 0
+test stringmatch-5.41 {Tcl_StringMatch: skip correct number of ']'} {
+    string match {[A-]]x} Ax
+} 1
+test stringmatch-5.42 {Tcl_StringMatch: skip correct number of ']'} {
+    string match {[A-]]x} \ue1x
+} 0
+test stringmatch-5.43 {Tcl_StringMatch: skip correct number of ']'} utf8 {
+    string match \[A-]\ue1]x \ue1x
+} 1
+test stringmatch-5.44 {Tcl_StringMatch: skip correct number of ']'} {
+    string match {[A-]h]x} hx
+} 1
+test stringmatch-5.45 {Tcl_StringMatch} {
+    # if (*pattern == '\0')
+    # badly formed pattern, still treats as a set
+
+    string match {[a} a
+} 1
+test stringmatch-5.46 {Tcl_StringMatch} {
+    string match {a\*b} a*b
+} 1
+test stringmatch-5.47 {Tcl_StringMatch} {
+    string match {a\*b} ab
+} 0
+test stringmatch-5.48 {Tcl_StringMatch} {
+    string match {a\*\?\[\]\\\x} "a*?\[\]\\x"
+} 1
+test stringmatch-5.49 {Tcl_StringMatch} {
+    string match ** ""
+} 1
+test stringmatch-5.50 {Tcl_StringMatch} {
+    string match *. ""
+} 0
+test stringmatch-5.51 {Tcl_StringMatch} {
+    string match "" ""
+} 1
+
+# 'string match' doesn't support ^, which is different
+# from 'scan'
+
+test stringmatch-6.1 {bracket in charset} {
+    string match {a[]b]c} {a]c}
+} 0
+
+test stringmatch-6.2 {bracket in charset} {
+    string match {a[]b]c} {abc}
+} 0
+
+test stringmatch-6.3 {charset with ^} {
+    string match {a[^]b]c} {axc}
+} 0
+
+test stringmatch-6.4 {charset with ^} {
+    string match {a[^]b]c} {a]c}
+} 0
+
+test stringmatch-6.5 {charset with ^} {
+    string match {a[^bc]d} {axd}
+} 0
+
+test stringmatch-6.6 {charset with ^} {
+    string match {a[\]]c} {a]c}
+} 0
+
+test stringmatch=7.1 {short string with ?} {
+    string match {ab?} ab
+} 0
+
+test stringmatch=7.1 {multiple * to end} {
+    string match {ab**} ab
+} 1
+
+testreport
diff --git a/jim/tests/subst.test b/jim/tests/subst.test
new file mode 100755 (executable)
index 0000000..353af5f
--- /dev/null
@@ -0,0 +1,178 @@
+# Commands covered:  subst
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-2000 Ajuba Solutions.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: subst.test,v 1.6.2.1 2001/04/03 22:54:38 hobbs Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+test subst-1.0 {basics} {
+    subst {\$x}
+} "\$x"
+
+test subst-1.1 {basics} {
+    list [catch {subst} msg]
+} {1}
+test subst-1.2 {basics} {
+    list [catch {subst a b c} msg]
+} {1}
+
+test subst-2.1 {simple strings} {
+    subst {}
+} {}
+test subst-2.2 {simple strings} {
+    subst a
+} a
+test subst-2.3 {simple strings} {
+    subst abcdefg
+} abcdefg
+
+test subst-3.1 {backslash substitutions} {
+    subst {\x\$x\[foo bar]\\}
+} "x\$x\[foo bar]\\"
+
+test subst-4.1 {variable substitutions} {
+    set a 44
+    subst {$a}
+} {44}
+test subst-4.2 {variable substitutions} {
+    set a 44
+    subst {x$a.y{$a}.z}
+} {x44.y{44}.z}
+test subst-4.3 {variable substitutions} {
+    catch {unset a}
+    set a(13) 82
+    set i 13
+    subst {x.$a($i)}
+} {x.82}
+catch {unset a}
+set long {This is a very long string, intentionally made so long that it
+       will overflow the static character size for dstrings, so that
+       additional memory will have to be allocated by subst.  That way,
+       if the subst procedure forgets to free up memory while returning
+       an error, there will be memory that isn't freed (this will be
+       detected when the tests are run under a checking memory allocator
+       such as Purify).}
+test subst-4.4 {variable substitutions} {
+    list [catch {subst {$long $a}} msg] $msg
+} {1 {can't read "a": no such variable}}
+
+test subst-5.1 {command substitutions} {
+    subst {[concat {}]}
+} {}
+test subst-5.2 {command substitutions} {
+    subst {[concat A test string]}
+} {A test string}
+test subst-5.3 {command substitutions} {
+    subst {x.[concat foo].y.[concat bar].z}
+} {x.foo.y.bar.z}
+test subst-5.4 {command substitutions} {
+    list [catch {subst {$long [set long] [bogus_command]}} msg] $msg
+} {1 {invalid command name "bogus_command"}}
+
+test subst-6.1 {clear the result after command substitution} {
+    catch {unset a}
+    list [catch {subst {[concat foo] $a}} msg] $msg
+} {1 {can't read "a": no such variable}}
+
+test subst-7.1 {switches} {
+    list [catch {subst foo bar} msg]
+} {1}
+test subst-7.2 {switches} {
+    list [catch {subst -no bar} msg]
+} {1}
+test subst-7.3 {switches} {
+    list [catch {subst -bogus bar} msg]
+} {1}
+test subst-7.4 {switches} {
+    set x 123
+    subst -nobackslashes {abc $x [expr 1+2] \\\x41}
+} {abc 123 3 \\\x41}
+test subst-7.5 {switches} {
+    set x 123
+    subst -nocommands {abc $x [expr 1+2] \\\x41}
+} {abc 123 [expr 1+2] \A}
+test subst-7.6 {switches} {
+    set x 123
+    subst -novariables {abc $x [expr 1+2] \\\x41}
+} {abc $x 3 \A}
+test subst-7.7 {switches} {
+    set x 123
+    subst -nov -nob -noc {abc $x [expr 1+2] \\\x41}
+} {abc $x [expr 1+2] \\\x41}
+
+test subst-8.1 {return in a subst} {
+    subst {foo [return {x}; bogus code] bar}
+} {foo x bar}
+test subst-8.2 {return in a subst} {
+    subst {foo [return x ; bogus code] bar}
+} {foo x bar}
+test subst-8.3 {return in a subst} {
+    subst {foo [if 1 { return {x}; bogus code }] bar}
+} {foo x bar}
+test subst-8.4 {return in a subst} {
+    subst {[eval {return hi}] there}
+} {hi there}
+test subst-8.5 {return in a subst} {
+    subst {foo [return {]}; bogus code] bar}
+} {foo ] bar}
+
+test subst-9.1 {error in a subst} {
+    list [catch {subst {[error foo; bogus code]bar}} msg] $msg
+} {1 foo}
+test subst-9.2 {error in a subst} {
+    list [catch {subst {[if 1 { error foo; bogus code}]bar}} msg] $msg
+} {1 foo}
+
+test subst-10.1 {break in a subst} {
+    subst {foo [break; bogus code] bar}
+} {foo }
+test subst-10.2 {break in a subst} {
+    subst {foo [break; return x; bogus code] bar}
+} {foo }
+test subst-10.3 {break in a subst} {
+    subst {foo [if 1 { break; bogus code}] bar}
+} {foo }
+test subst-10.4 {break in a subst, parse error} {
+    subst {foo [break ; set a {}{} ; stuff] bar}
+} {foo }
+test subst-10.5 {break in a subst, parse error} {
+    subst {foo [break ;set bar baz ;set a {}{} ; stuff] bar}
+} {foo }
+
+test subst-11.1 {continue in a subst} {
+    subst {foo [continue; bogus code] bar}
+} {foo  bar}
+test subst-11.2 {continue in a subst} {
+    subst {foo [continue; return x; bogus code] bar}
+} {foo  bar}
+test subst-11.3 {continue in a subst} {
+    subst {foo [if 1 { continue; bogus code}] bar}
+} {foo  bar}
+
+test subst-12.1 {lone $} {
+    subst {$}
+} {$}
+
+test subst-12.2 {lone $} {
+    set a 1
+    subst -novar {${a}}
+} {${a}}
+
+test subst-12.3 {variable inside [] with -noc} {
+    set a 1
+    subst -noc {x[join $a]y}
+} {x[join 1]y}
+
+
+# cleanup
+testreport
diff --git a/jim/tests/tailcall.test b/jim/tests/tailcall.test
new file mode 100755 (executable)
index 0000000..eaa48cc
--- /dev/null
@@ -0,0 +1,115 @@
+# vim:se syntax=tcl:
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd tailcall
+needs cmd try tclcompat
+
+test tailcall-1.1 {Basic tailcall} {
+       # Demo -- a tail-recursive factorial function
+       proc fac {x {val 1}} {
+               if {$x <= 2} {
+                       expr {$x * $val}
+               } else {
+                       tailcall fac [expr {$x -1}] [expr {$x * $val}]
+               }
+       }
+       fac 10
+} {3628800}
+
+test tailcall-1.2 {Tailcall in try} {
+       set x 0
+       proc a {} { upvar x x; incr x }
+       proc b {} { upvar x x; incr x 4; try { tailcall a } finally { incr x 8 }}
+       b
+       set x
+} {13}
+
+test tailcall-1.3 {Tailcall does return} {
+       set x 0
+       proc a {} { upvar x x; incr x }
+       proc b {} { upvar x x; incr x 4; tailcall a; incr x 8}
+       b
+       set x
+} {5}
+
+test tailcall-1.5 {interaction of uplevel and tailcall} {
+       proc a {cmd} {
+               tailcall $cmd
+       }
+       proc b {} {
+               lappend result [uplevel 1 a c]
+               lappend result [uplevel 1 a c]
+       }
+       proc c {} {
+               return c
+       }
+       a b
+} {c c}
+
+test tailcall-1.6 {tailcall pass through return} {
+       proc a {script} {
+               # return from $script should pass through back to the caller
+               tailcall foreach i {1 2 3} $script
+       }
+       proc b {} {
+               a {return ok}
+               # Should not get here
+               return bad
+       }
+       b
+} {ok}
+
+test tailcall-1.7 {tailcall with namespaces} jim {
+       proc a::b {} {
+               proc c {} {
+                       return 1
+               }
+               set d [local lambda {} { c }]
+               # $d should resolve in namespace 'a', not ""
+               tailcall $d
+       }
+       a::b
+} 1
+
+test tailcall-1.8 {tailcall with local} jim {
+       proc a {} {
+               tailcall [local proc b {} { return c }]
+       }
+       a
+} {c}
+
+test tailcall-1.9 {tailcall with large number of invocations} {
+       proc a {n} {
+               if {$n == 0} {
+                       return 1
+               }
+               incr n -1
+               tailcall a $n
+       }
+       a 1000
+} 1
+
+test tailcall-1.10 {tailcall through uplevel} {
+       proc a {} { tailcall b }
+       proc b {} { uplevel 1 c }
+       proc c {} { tailcall d }
+       proc d {} { return [info level] }
+       a
+} 1
+
+test tailcall-1.11 {chained tailcall} {
+       proc a {} { b }
+       proc b {} { tailcall tailcall c }
+       proc c {} { return [info level] }
+       a
+} 1
+
+test tailcall-1.12 {uplevel tailcall} {
+       proc a {} { b }
+       proc b {} { uplevel 1 tailcall c }
+       proc c {} { return [info level] }
+       a
+} 1
+
+testreport
diff --git a/jim/tests/testing.tcl b/jim/tests/testing.tcl
new file mode 100755 (executable)
index 0000000..8bfd22d
--- /dev/null
@@ -0,0 +1,256 @@
+# Common code
+set testinfo(verbose) 0
+set testinfo(numpass) 0
+set testinfo(stoponerror) 0
+set testinfo(numfail) 0
+set testinfo(numskip) 0
+set testinfo(numtests) 0
+set testinfo(failed) {}
+
+set testdir [file dirname [info script]]
+set bindir [file dirname [info nameofexecutable]]
+
+if {[lsearch $argv "-verbose"] >= 0 || [info exists env(testverbose)]} {
+       incr testinfo(verbose)
+}
+if {[lsearch $argv "-stoponerror"] >= 0 || [info exists env(stoponerror)]} {
+       incr testinfo(stoponerror)
+}
+
+proc needs {type what {packages {}}} {
+       if {$type eq "constraint"} {
+               if {![info exists ::tcltest::testConstraints($what)]} {
+                       set ::tcltest::testConstraints($what) 0
+               }
+               if {![set ::tcltest::testConstraints($what)]} {
+                       skiptest " (constraint $what)"
+               }
+               return
+       }
+       if {$type eq "cmd"} {
+               # Does it exist already?
+               if {[info commands $what] ne ""} {
+                       return
+               }
+               if {$packages eq ""} {
+                       # e.g. exec command is in exec package
+                       set packages $what
+               }
+               foreach p $packages {
+                       catch {package require $p}
+               }
+               if {[info commands $what] ne ""} {
+                       return
+               }
+               skiptest " (command $what)"
+       }
+       error "Unknown needs type: $type"
+}
+
+proc skiptest {{msg {}}} {
+       puts [format "%16s:   --- skipped$msg" $::argv0]
+       exit 0
+}
+
+# If tcl, just use tcltest
+if {[catch {info version}]} {
+       package require Tcl 8.5
+       package require tcltest 2.1
+       namespace import tcltest::*
+
+       if {$testinfo(verbose)} {
+               configure -verbose bps
+       }
+       testConstraint utf8 1
+       testConstraint tcl 1
+       proc testreport {} {
+               ::tcltest::cleanupTests
+       }
+       return
+}
+
+lappend auto_path $testdir $bindir [file dirname [pwd]]
+
+# For Jim, this is reasonable compatible tcltest
+proc makeFile {contents name} {
+       set f [open $name w]
+       stdout puts "About to 'puts $f $contents'"
+       puts $f $contents
+       close $f
+       return $name
+}
+
+proc removeFile {name} {
+       file delete $name
+}
+
+# In case tclcompat is not selected
+if {![exists -proc puts]} {
+       proc puts {{-nonewline {}} {chan stdout} msg} {
+               if {${-nonewline} ni {-nonewline {}}} {
+                       ${-nonewline} puts $msg
+               } else {
+                       $chan puts {*}${-nonewline} $msg
+               }
+       }
+       proc close {chan args} {
+               $chan close {*}$args
+       }
+       proc fileevent {args} {
+               {*}$args
+       }
+}
+
+proc script_source {script} {
+       lassign [info source $script] f l
+       if {$f ne ""} {
+               puts "At      : $f:$l"
+               return \t$f:$l
+       }
+}
+
+proc error_source {} {
+       lassign [info stacktrace] p f l
+       if {$f ne ""} {
+               puts "At      : $f:$l"
+               return \t$f:$l
+       }
+}
+
+proc package-or-skip {name} {
+       if {[catch {
+               package require $name
+       }]} {
+               puts [format "%16s:   --- skipped" $::argv0]
+               exit 0
+       }
+}
+
+proc testConstraint {constraint bool} {
+       set ::tcltest::testConstraints($constraint) $bool
+}
+
+testConstraint {utf8} [expr {[string length "\xc2\xb5"] == 1}]
+testConstraint {references} [expr {[info commands ref] ne ""}]
+testConstraint {jim} 1
+testConstraint {tcl} 0
+
+proc bytestring {x} {
+       return $x
+}
+
+# Note: We don't support -output or -errorOutput yet
+proc test {id descr args} {
+       set a [dict create -returnCodes {ok return} -match exact -result {} -constraints {} -body {} -setup {} -cleanup {}]
+       if {[lindex $args 0] ni [dict keys $a]} {
+               if {[llength $args] == 2} {
+                       lassign $args body result constraints
+               } elseif {[llength $args] == 3} {
+                       lassign $args constraints body result
+               } else {
+                       return -code error "$id: Wrong syntax for tcltest::test v1"
+               }
+               tailcall test $id $descr -body $body -result $result -constraints $constraints
+       }
+       # tcltest::test v2 syntax
+       array set a $args
+
+       incr ::testinfo(numtests)
+       if {$::testinfo(verbose)} {
+               puts -nonewline "$id "
+       }
+
+       foreach c $a(-constraints) {
+               if {[info exists ::tcltest::testConstraints($c)]} {
+                       if {$::tcltest::testConstraints($c)} {
+                               continue
+                       }
+                       incr ::testinfo(numskip)
+                       if {$::testinfo(verbose)} {
+                               puts "SKIP"
+                       }
+                       return
+               }
+       }
+
+       catch {uplevel 1 $a(-setup)}
+       set rc [catch {uplevel 1 $a(-body)} result opts]
+       catch {uplevel 1 $a(-cleanup)}
+
+       if {[info return $rc] ni $a(-returnCodes) && $rc ni $a(-returnCodes)} {
+               set ok 0
+               set expected "rc=$a(-returnCodes) result=$a(-result)"
+               set result "rc=[info return $rc] result=$result"
+       } else {
+               if {$a(-match) eq "exact"} {
+                       set ok [string equal $a(-result) $result]
+               } elseif {$a(-match) eq "glob"} {
+                       set ok [string match $a(-result) $result]
+               } elseif {$a(-match) eq "regexp"} {
+                       set ok [regexp $a(-result) $result]
+               } else {
+                       return -code error "$id: unknown match type: $a(-match)"
+               }
+               set expected $a(-result)
+       }
+
+       if {$ok} {
+               if {$::testinfo(verbose)} {
+                       puts "OK  $descr"
+               }
+               incr ::testinfo(numpass)
+               return
+       }
+
+       if {!$::testinfo(verbose)} {
+               puts -nonewline "$id "
+       }
+       puts "ERR $descr"
+       if {$rc in {0 2}} {
+               set source [script_source $a(-body)]
+       } else {
+               set source [error_source]
+       }
+       puts "Expected: '$expected'"
+       puts "Got     : '$result'"
+       puts ""
+       incr ::testinfo(numfail)
+       lappend ::testinfo(failed) [list $id $descr $source $expected $result]
+       if {$::testinfo(stoponerror)} {
+               exit 1
+       }
+}
+
+proc ::tcltest::cleanupTests {} {
+       tailcall testreport
+}
+
+proc testreport {} {
+       if {$::testinfo(verbose)} {
+               puts -nonewline "\n$::argv0"
+       } else {
+               puts -nonewline [format "%16s" $::argv0]
+       }
+       puts [format ": Total %5d   Passed %5d  Skipped %5d  Failed %5d" \
+               $::testinfo(numtests) $::testinfo(numpass) $::testinfo(numskip) $::testinfo(numfail)]
+       if {$::testinfo(numfail)} {
+               puts [string repeat - 60]
+               puts "FAILED: $::testinfo(numfail)"
+               foreach failed $::testinfo(failed) {
+                       foreach {id descr source expected result} $failed {}
+                       puts "$source\t$id"
+               }
+               puts [string repeat - 60]
+       }
+       if {$::testinfo(numfail)} {
+               exit 1
+       }
+}
+
+proc testerror {} {
+       error "deliberate error"
+}
+
+if {$testinfo(verbose)} {
+       puts "==== $argv0 ===="
+}
diff --git a/jim/tests/testio.in b/jim/tests/testio.in
new file mode 100755 (executable)
index 0000000..af44aee
--- /dev/null
@@ -0,0 +1,2 @@
+One line here
+^
\ No newline at end of file
diff --git a/jim/tests/timer.test b/jim/tests/timer.test
new file mode 100755 (executable)
index 0000000..26ffa0a
--- /dev/null
@@ -0,0 +1,454 @@
+# This file contains a collection of tests for the procedures in the
+# file tclTimer.c, which includes the "after" Tcl command.  Sourcing
+# this file into Tcl runs the tests and generates output for errors.
+# No output means no errors were found.
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1997 by Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: timer.test,v 1.7.2.1 2001/10/13 01:14:19 hobbs Exp $
+
+source [file dirname [info script]]/testing.tcl
+needs cmd after eventloop
+
+test timer-1.1 {Tcl_CreateTimerHandler procedure} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x ""
+    foreach i {20 40 200 10 30} {
+       after $i lappend x $i
+    }
+    after 50
+    update
+    set x
+} {10 20 30 40}
+
+test timer-2.1 {Tcl_DeleteTimerHandler procedure} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x ""
+    foreach i {20 40 60 10 30} {
+       after $i lappend x $i
+    }
+    after cancel lappend x 60
+    after cancel lappend x 10
+    after 50
+    update
+    set x
+} {20 30 40}
+
+# No tests for Tcl_ServiceTimer or ResetTimer, since it is already tested
+# above.
+
+test timer-3.1 {TimerHandlerEventProc procedure: event masks} {
+    set x start
+    after 20 { set x fired }
+    update idletasks
+    set result $x
+    after 40
+    update
+    lappend result $x
+} {start fired}
+test timer-3.2 {TimerHandlerEventProc procedure: multiple timers} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    foreach i {40 120 200} {
+       after $i lappend x $i
+    }
+    after 50
+    set result ""
+    set x ""
+    update
+    lappend result $x
+    after 80
+    update
+    lappend result $x
+    after 80
+    update
+    lappend result $x
+} {40 {40 120} {40 120 200}}
+test timer-3.3 {TimerHandlerEventProc procedure: reentrant timer deletion} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x {}
+    after 20 lappend x 20
+    set i [after 60 lappend x 60]
+    after 40 after cancel $i
+    after 80
+    update
+    set x
+} 20
+test timer-3.4 {TimerHandlerEventProc procedure: all expired timers fire} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x {}
+    after 20 lappend x a
+    after 40 lappend x b
+    after 60 lappend x c
+    after 70
+    vwait x
+    set x
+} {a b c}
+test timer-3.5 {TimerHandlerEventProc procedure: reentrantly added timers don't fire} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x {}
+    after 20 {lappend x a; after 0 lappend x b}
+    after 20
+    vwait x
+    set x
+} a
+test timer-3.6 {TimerHandlerEventProc procedure: reentrantly added timers don't fire} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x {}
+    after 20 {lappend x a; after 20 lappend x b; after 20}
+    after 20
+    vwait x
+    set result $x
+    vwait x
+    lappend result $x
+} {a {a b}}
+
+# No tests for Tcl_DoWhenIdle:  it's already tested by other tests
+# below.
+
+test timer-4.1 {Tcl_CancelIdleCall procedure} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x before
+    set y before
+    set z before
+    after idle set x after1
+    after idle set y after2
+    after idle set z after3
+    after cancel set y after2
+    update idletasks
+    concat $x $y $z
+} {after1 before after3}
+test timer-4.2 {Tcl_CancelIdleCall procedure} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x before
+    set y before
+    set z before
+    after idle set x after1
+    after idle set y after2
+    after idle set z after3
+    after cancel set x after1
+    update idletasks
+    concat $x $y $z
+} {before after2 after3}
+
+test timer-5.1 {Tcl_ServiceIdle, self-rescheduling handlers} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x 1
+    set y 23
+    after idle {incr x; after idle {incr x; after idle {incr x}}}
+    after idle {incr y}
+    vwait x
+    set result "$x $y"
+    update idletasks
+    lappend result $x
+} {2 24 4}
+
+test timer-6.1 {Tcl_AfterCmd procedure, basics} {
+    list [catch {after} msg] $msg
+} {1 {wrong # args: should be "after option ?arg ...?"}}
+test timer-6.2 {Tcl_AfterCmd procedure, basics} jim {
+    list [catch {after 2x} msg] $msg
+} {1 {bad argument "2x": must be cancel, idle, or info}}
+test timer-6.3 {Tcl_AfterCmd procedure, basics} jim {
+    list [catch {after gorp} msg] $msg
+} {1 {bad argument "gorp": must be cancel, idle, or info}}
+test timer-6.4 {Tcl_AfterCmd procedure, ms argument} {
+    set x before
+    after 80 {set x after}
+    after 40
+    update
+    set y $x
+    after 80
+    update
+    list $y $x
+} {before after}
+test timer-6.5 {Tcl_AfterCmd procedure, ms argument} {
+    set x before
+    after 60 {set x after}
+    after 40
+    update
+    set y $x
+    after 40
+    update
+    list $y $x
+} {before after}
+test timer-6.6 {Tcl_AfterCmd procedure, cancel option} {
+    list [catch {after cancel} msg] $msg
+} {1 {wrong # args: should be "after cancel id|command"}}
+test timer-6.7 {Tcl_AfterCmd procedure, cancel option} {
+    after cancel after#1
+} {}
+test timer-6.8 {Tcl_AfterCmd procedure, cancel option} {
+    after cancel {foo bar}
+} {}
+test timer-6.9 {Tcl_AfterCmd procedure, cancel option} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x before
+    set y [after 20 set x after]
+    after cancel $y
+    after 40
+    update
+    set x
+} {before}
+test timer-6.10 {Tcl_AfterCmd procedure, cancel option} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x before
+    after 20 set x after
+    after cancel set x after
+    after 40
+    update
+    set x
+} {before}
+test timer-6.11 {Tcl_AfterCmd procedure, cancel option} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x before
+    after 20 set x after
+    set id [after 60 set x after]
+    after cancel $id
+    after 40
+    update
+    set y $x
+    set x cleared
+    after 40
+    update
+    list $y $x
+} {after cleared}
+test timer-6.12 {Tcl_AfterCmd procedure, cancel option} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x first
+    after idle lappend x second
+    after idle lappend x third
+    set i [after idle lappend x fourth]
+    after cancel {lappend x second}
+    after cancel $i
+    update idletasks
+    set x
+} {first third}
+test timer-6.13 {Tcl_AfterCmd procedure, cancel option, multiple arguments for command} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x first
+    after idle lappend x second
+    after idle lappend x third
+    set i [after idle lappend x fourth]
+    after cancel lappend x second
+    after cancel $i
+    update idletasks
+    set x
+} {first third}
+test timer-6.14 {Tcl_AfterCmd procedure, cancel option, cancel during handler, used to dump core} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set id [
+       after 20 {
+           set x done
+           after cancel $id
+       }
+    ]
+    vwait x
+} {}
+test timer-6.16 {Tcl_AfterCmd procedure, idle option} {
+    list [catch {after idle} msg] $msg
+} {1 {wrong # args: should be "after idle script ?script ...?"}}
+test timer-6.17 {Tcl_AfterCmd procedure, idle option} {
+    set x before
+    after idle {set x after}
+    set y $x
+    update idletasks
+    list $y $x
+} {before after}
+test timer-6.18 {Tcl_AfterCmd procedure, idle option} {
+    set x before
+    after idle set x after
+    set y $x
+    update idletasks
+    list $y $x
+} {before after}
+
+test timer-6.23 {Tcl_AfterCmd procedure, no option, script with NULL} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x "hello world"
+    after 1 "set x ab\0cd"
+    after 10
+    update
+    string length $x
+} {5}
+test timer-6.24 {Tcl_AfterCmd procedure, no option, script with NULL} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x "hello world"
+    after 1 set x ab\0cd
+    after 10
+    update
+    string length $x
+} {5}
+test timer-6.25 {Tcl_AfterCmd procedure, cancel option, script with NULL} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x "hello world"
+    after 1 set x ab\0cd
+    after cancel "set x ab\0ef"
+    set x [llength [after info]]
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x
+} {1}
+test timer-6.26 {Tcl_AfterCmd procedure, cancel option, script with NULL} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x "hello world"
+    after 1 set x ab\0cd
+    after cancel set x ab\0ef
+    set y [llength [after info]]
+    foreach i [after info] {
+       after cancel $i
+    }
+    set y
+} {1}
+test timer-6.27 {Tcl_AfterCmd procedure, idle option, script with NULL} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x "hello world"
+    after idle "set x ab\0cd"
+    update
+    string length $x
+} {5}
+test timer-6.28 {Tcl_AfterCmd procedure, idle option, script with NULL} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x "hello world"
+    after idle set x ab\0cd
+    update
+    string length $x
+} {5}
+test timer-6.29 {Tcl_AfterCmd procedure, info option, script with NULL} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    set x "hello world"
+    set id junk
+    set id [after 10 set x ab\0cd]
+    update
+    set y [string length [lindex [lindex [after info $id] 0] 2]]
+    foreach i [after info] {
+       after cancel $i
+    }
+    set y
+} {5}
+
+set event [after idle foo bar]
+scan $event after#%d id
+
+test timer-7.1 {GetAfterEvent procedure} {
+    list [catch {after info xfter#$id} msg] $msg
+} "1 {event \"xfter#$id\" doesn't exist}"
+test timer-7.2 {GetAfterEvent procedure} {
+    list [catch {after info afterx$id} msg] $msg
+} "1 {event \"afterx$id\" doesn't exist}"
+test timer-7.3 {GetAfterEvent procedure} {
+    list [catch {after info after#ab} msg] $msg
+} {1 {event "after#ab" doesn't exist}}
+test timer-7.4 {GetAfterEvent procedure} {
+    list [catch {after info after#} msg] $msg
+} {1 {event "after#" doesn't exist}}
+test timer-7.5 {GetAfterEvent procedure} {
+    list [catch {after info after#${id}x} msg] $msg
+} "1 {event \"after#${id}x\" doesn't exist}"
+test timer-7.6 {GetAfterEvent procedure} {
+    list [catch {after info afterx[expr $id+1]} msg] $msg
+} "1 {event \"afterx[expr $id+1]\" doesn't exist}"
+after cancel $event
+
+test timer-8.1 {AfterProc procedure} {
+    set x before
+    proc foo {} {
+       set x untouched
+       after 20 {set x after}
+       after 200
+       update
+       return $x
+    }
+    list [foo] $x
+} {untouched after}
+test timer-8.2 {AfterProc procedure} {
+    catch {rename bgerror {}}
+    proc bgerror msg {
+       set ::x $msg
+    }
+    set x empty
+    after 20 {error "After error"}
+    after 200
+    set y $x
+    update
+    catch {rename bgerror {}}
+    list $y $x
+} {empty {After error}}
+
+test timer-8.4 {AfterProc procedure, deleting handler from itself} {
+    foreach i [after info] {
+       after cancel $i
+    }
+    proc foo {} {
+       global x
+       set x {}
+       foreach i [after info] {
+           lappend x [after info $i]
+       }
+       after cancel foo
+    }
+    after 1000 {error "I shouldn't ever have executed"}
+    after idle foo
+    update idletasks
+    set x
+} {{{error "I shouldn't ever have executed"} timer}}
+
+foreach i [after info] {
+    after cancel $i
+}
+
+testreport
diff --git a/jim/tests/tree.test b/jim/tests/tree.test
new file mode 100755 (executable)
index 0000000..5a7cf74
--- /dev/null
@@ -0,0 +1,115 @@
+source [file dirname [info script]]/testing.tcl
+needs cmd tree
+needs cmd ref
+
+proc dputs {msg} {
+       #puts $msg
+}
+
+test tree-1.1 "Create tree" {
+       set pt [tree]
+       return 1
+} {1}
+
+test tree-1.2 "Root node depth" {
+       $pt depth root
+} {0}
+
+test tree-1.3 "Access invalid node" {
+       list [catch {
+               $pt depth bogus
+       } msg] $msg
+} {1 {key "bogus" not known in dictionary}}
+
+test tree-1.4 "Set key/value" {
+       $pt set root key value
+       $pt set root type root
+       $pt set root name rootnode
+       $pt set root values {}
+       $pt get root key
+} {value}
+
+test tree-1.5 "Add child node" {
+       set n [$pt insert root]
+       $pt set $n childkey childvalue
+       $pt set $n type level1type
+       $pt set $n name childnode1
+       $pt set $n values {label testlabel}
+       $pt get $n childkey
+} {childvalue}
+
+test tree-1.6 "Add child, child node" {
+       set nn [$pt insert $n]
+       $pt set $nn childkey2 childvalue2
+       $pt set $nn type level2type
+       $pt set $nn name childnode2
+       $pt set $nn values {label testlabel storage none}
+       $pt get $nn childkey2
+} {childvalue2}
+
+test tree-1.7 "Key exists true" {
+       $pt keyexists $nn childkey2
+} {1}
+
+test tree-1.7 "Key exists false" {
+       $pt keyexists $n boguskey
+} {0}
+
+test tree-1.8 "lappend" {
+       $pt lappend $n newkey first
+       $pt lappend $n newkey second
+       $pt lappend $n newkey third
+       $pt lappend $n newkey last
+} {first second third last}
+
+test tree-2.0 "Add more nodes" {
+       set c [$pt insert root]
+       $pt set $c name root.c2
+       set c [$pt insert root]
+       $pt set $c name root.c3
+       set c [$pt insert $n]
+       $pt set $c name n.c4
+       set c [$pt insert $n]
+       $pt set $c name n.c5
+       set c [$pt insert $c]
+       $pt set $c name n.c5.c6
+       return 1
+} {1}
+
+test tree-2.1 "walk dfs" {
+       set result {}
+       dputs ""
+       $pt walk root dfs {action n} {
+               set indent [string repeat "  " [$pt depth $n]]
+               if {$action == "enter"} {
+                       lappend result [$pt get $n name]
+                       dputs "$indent[$pt get $n name]"
+               }
+       }
+       dputs ""
+       set result
+} {rootnode childnode1 childnode2 n.c4 n.c5 n.c5.c6 root.c2 root.c3}
+
+test tree-2.2 "walk dfs exit" {
+       set result {}
+       $pt walk root dfs {action n} {
+               if {$action == "exit"} {
+                       lappend result [$pt get $n name]
+               }
+       }
+       set result
+} {childnode2 n.c4 n.c5.c6 n.c5 childnode1 root.c2 root.c3 rootnode}
+
+test tree-2.3 "walk bfs" {
+       set result {}
+       $pt walk root bfs {action n} {
+               if {$action == "enter"} {
+                       lappend result [$pt get $n name]
+               }
+       }
+       set result
+} {rootnode childnode1 root.c2 root.c3 childnode2 n.c4 n.c5 n.c5.c6}
+
+$pt destroy
+
+testreport
diff --git a/jim/tests/try.test b/jim/tests/try.test
new file mode 100755 (executable)
index 0000000..a2bb38a
--- /dev/null
@@ -0,0 +1,117 @@
+source [file dirname [info script]]/testing.tcl
+needs cmd try tclcompat
+
+test try-1.1 "Simple case" {
+       try {
+               set x 0
+       } finally {
+               incr x
+       }
+} 0
+
+test try-1.2 "Error in body" {
+       list [catch {
+               try {
+                       set x 0
+                       error message
+               } finally {
+                       incr x
+               }
+       } msg] $msg $x
+} {1 message 1}
+
+test try-1.3 "Error in finally" {
+       list [catch {
+               try {
+                       set x 0
+               } finally {
+                       incr x
+                       error finally
+               }
+       } msg] $msg $x
+} {1 finally 1}
+
+test try-1.4 "Error in both" {
+       list [catch {
+               try {
+                       set x 0
+                       error message
+               } finally {
+                       incr x
+                       error finally
+               }
+       } msg] $msg $x
+} {1 finally 1}
+
+test try-1.5 "break in body" {
+       list [catch {
+               try {
+                       set x 0
+                       break
+               } finally {
+                       incr x
+               }
+       } msg] $msg $x
+} {3 {} 1}
+
+test try-1.6 "break in finally" {
+       list [catch {
+               try {
+                       set x 0
+               } finally {
+                       incr x
+                       break
+               }
+       } msg] $msg $x
+} {3 {} 1}
+
+test try-1.7 "return value from try, not finally" {
+       list [catch {
+               try {
+                       set x 0
+               } finally {
+                       incr x
+               }
+       } msg] $msg $x
+} {0 0 1}
+
+test try-1.8 "return from within try" {
+       proc a {} {
+               try {
+                       return 1
+               }
+               # notreached
+               return 2
+       }
+       a
+} {1}
+
+test try-1.9 "return -code from within try" {
+       proc a {} {
+               try {
+                       return -code break text
+               }
+               # notreached
+               return 2
+       }
+       list [catch a msg] $msg
+} {3 text}
+
+proc c {} {
+       try {
+               error here
+       } on error {msg opts} {
+               # jim can do simply: 
+               if {[catch {incr opts(-level)}]} {
+                       # Must be Tcl
+                       dict incr opts -level
+               }
+               return {*}$opts $msg
+       }
+}
+
+test try-3.1 "rethrow error in try/on handler" {
+       list [catch c msg] $msg
+} {1 here}
+
+testreport
diff --git a/jim/tests/uplevel.test b/jim/tests/uplevel.test
new file mode 100755 (executable)
index 0000000..004e387
--- /dev/null
@@ -0,0 +1,124 @@
+# Commands covered:  uplevel
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: uplevel.test,v 1.6 2000/04/10 17:19:05 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+proc a {x y} {
+    newset z [expr $x+$y]
+    return $z
+}
+proc newset {name value} {
+    uplevel set $name $value
+    uplevel 1 {uplevel 1 {set xyz 22}}
+}
+proc b {x y} {
+    uplevel #0 set $x $y
+}
+
+test uplevel-1.1 {simple operation} {
+    set xyz 0
+    a 22 33
+} 55
+test uplevel-1.2 {command is another uplevel command} {
+    set xyz 0
+    a 22 33
+    set xyz
+} 22
+
+proc a1 {} {
+    b1
+    global a a1
+    set a $x
+    set a1 $y
+}
+proc b1 {} {
+    c1
+    global b b1
+    set b $x
+    set b1 $y
+}
+proc c1 {} {
+    uplevel 1 set x 111
+    uplevel #2 set y 222
+    uplevel 2 set x 333
+    uplevel #1 set y 444
+    uplevel 3 set x 555
+    uplevel #0 set y 666
+}
+a1
+test uplevel-2.1 {relative and absolute uplevel} {set a} 333
+test uplevel-2.2 {relative and absolute uplevel} {set a1} 444
+test uplevel-2.3 {relative and absolute uplevel} {set b} 111
+test uplevel-2.4 {relative and absolute uplevel} {set b1} 222
+test uplevel-2.5 {relative and absolute uplevel} {set x} 555
+test uplevel-2.6 {relative and absolute uplevel} {set y} 666
+
+test uplevel-3.1 {uplevel to same level} {
+    set x 33
+    uplevel #0 set x 44
+    set x
+} 44
+test uplevel-3.2 {uplevel to same level} {
+    set x 33
+    uplevel 0 set x
+} 33
+test uplevel-3.3 {uplevel to same level} {
+    set y xxx
+    proc a1 {} {set y 55; uplevel 0 set y 66; return $y}
+    a1
+} 66
+test uplevel-3.4 {uplevel to same level} {
+    set y zzz
+    proc a1 {} {set y 55; uplevel #1 set y}
+    a1
+} 55
+
+test uplevel-4.1 {error check: non-existent level} {
+    list [catch c1 msg] $msg
+} {1 {bad level "#2"}}
+test uplevel-4.2 {error check: non-existent level} {
+    proc c2 {} {uplevel 3 {set a b}}
+    list [catch c2 msg] $msg
+} {1 {bad level "3"}}
+test uplevel-4.3 {error check: not enough args} {
+    list [catch uplevel msg] $msg
+} {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}}
+test uplevel-4.4 {error check: not enough args} {
+    proc upBug {} {uplevel 1}
+    list [catch upBug msg] $msg
+} {1 {wrong # args: should be "uplevel ?level? command ?arg ...?"}}
+
+proc a2 {} {
+    uplevel a3
+}
+proc a3 {} {
+    global x y
+    set x [info level]
+    set y [info level 1]
+}
+a2
+test uplevel-5.1 {info level} {set x} 1
+test uplevel-5.2 {info level} {set y} a3
+
+test uplevel-6.1 {uplevel #0} {
+    b g1 g1val
+    set ::g1
+} g1val
+
+test uplevel-6.2 {uplevel #bad} {
+    catch {uplevel #bad set x 1}
+} 1
+
+testreport
diff --git a/jim/tests/upvar.test b/jim/tests/upvar.test
new file mode 100755 (executable)
index 0000000..261f7b9
--- /dev/null
@@ -0,0 +1,350 @@
+# Commands covered:  upvar
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands.  Sourcing this file into Tcl runs the tests and
+# generates output for errors.  No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: upvar.test,v 1.7 2000/04/10 17:19:05 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd array
+
+test upvar-1.1 {reading variables with upvar} {
+    proc p1 {a b} {set c 22; set d 33; p2}
+    proc p2 {} {upvar a x1 b x2 c x3 d x4; set a abc; list $x1 $x2 $x3 $x4 $a}
+    p1 foo bar
+} {foo bar 22 33 abc}
+test upvar-1.2 {reading variables with upvar} {
+    proc p1 {a b} {set c 22; set d 33; p2}
+    proc p2 {} {p3}
+    proc p3 {} {upvar 2 a x1 b x2 c x3 d x4; set a abc; list $x1 $x2 $x3 $x4 $a}
+    p1 foo bar
+} {foo bar 22 33 abc}
+test upvar-1.3 {reading variables with upvar} {
+    proc p1 {a b} {set c 22; set d 33; p2}
+    proc p2 {} {p3}
+    proc p3 {} {
+       upvar #1 a x1 b x2 c x3 d x4
+       set a abc
+       list $x1 $x2 $x3 $x4 $a
+    }
+    p1 foo bar
+} {foo bar 22 33 abc}
+test upvar-1.4 {reading variables with upvar} {
+    set x1 44
+    set x2 55
+    proc p1 {} {p2}
+    proc p2 {} {
+       upvar 2 x1 x1 x2 a
+       upvar #0 x1 b
+       set c $b
+       incr b 3
+       list $x1 $a $b
+    }
+    p1
+} {47 55 47}
+test upvar-1.5 {reading array elements with upvar} {
+    proc p1 {} {set a(0) zeroth; set a(1) first; p2}
+    proc p2 {} {upvar a(0) x; set x}
+    p1
+} {zeroth}
+
+test upvar-2.1 {writing variables with upvar} {
+    proc p1 {a b} {set c 22; set d 33; p2; list $a $b $c $d}
+    proc p2 {} {
+       upvar a x1 b x2 c x3 d x4
+       set x1 14
+       set x4 88
+    }
+    p1 foo bar
+} {14 bar 22 88}
+test upvar-2.2 {writing variables with upvar} {
+    set x1 44
+    set x2 55
+    proc p1 {x1 x2} {
+       upvar #0 x1 a
+       upvar x2 b
+       set a $x1
+       set b $x2
+    }
+    p1 newbits morebits
+    list $x1 $x2
+} {newbits morebits}
+test upvar-2.3 {writing variables with upvar} {
+    catch {unset x1}
+    catch {unset x2}
+    proc p1 {x1 x2} {
+       upvar #0 x1 a
+       upvar x2 b
+       set a $x1
+       set b $x2
+    }
+    p1 newbits morebits
+    list [catch {set x1} msg] $msg [catch {set x2} msg] $msg
+} {0 newbits 0 morebits}
+test upvar-2.4 {writing array elements with upvar} {
+    proc p1 {} {set a(0) zeroth; set a(1) first; list [p2] $a(0)}
+    proc p2 {} {upvar a(0) x; set x xyzzy}
+    p1
+} {xyzzy xyzzy}
+
+test upvar-3.1 {unsetting variables with upvar} {
+    proc p1 {a b} {set c 22; set d 33; p2; lsort [info vars]}
+    proc p2 {} {
+       upvar 1 a x1 d x2
+       unset x1 x2
+    }
+    p1 foo bar
+} {b c}
+test upvar-3.2 {unsetting variables with upvar} {
+    proc p1 {a b} {set c 22; set d 33; p2; lsort [info vars]}
+    proc p2 {} {
+       upvar 1 a x1 d x2
+       unset x1 x2
+       set x2 28
+    }
+    p1 foo bar
+} {b c d}
+test upvar-3.3 {unsetting variables with upvar} {
+    set x1 44
+    set x2 55
+    proc p1 {} {p2}
+    proc p2 {} {
+       upvar 2 x1 a
+       upvar #0 x2 b
+       unset a b
+    }
+    p1
+    list [info exists x1] [info exists x2]
+} {0 0}
+test upvar-3.4 {unsetting variables with upvar} {
+    set x1 44
+    set x2 55
+    proc p1 {} {
+       upvar x1 a x2 b
+       unset a b
+       set b 118
+    }
+    p1
+    list [info exists x1] [catch {set x2} msg] $msg
+} {0 0 118}
+test upvar-3.5 {unsetting array elements with upvar} {
+    proc p1 {} {
+       set a(0) zeroth
+       set a(1) first
+       set a(2) second
+       p2
+       lsort [array names a]
+    }
+    proc p2 {} {upvar a(0) x; unset x}
+    p1
+} {1 2}
+test upvar-3.6 {unsetting then resetting array elements with upvar} {
+    proc p1 {} {
+       set a(0) zeroth
+       set a(1) first
+       set a(2) second
+       p2
+       list [lsort [array names a]] [catch {set a(0)} msg] $msg
+    }
+    proc p2 {} {upvar a(0) x; unset x; set x 12345}
+    p1
+} {{0 1 2} 0 12345}
+
+test upvar-4.1 {nested upvars} {
+    set x1 88
+    proc p1 {a b} {set c 22; set d 33; p2}
+    proc p2 {} {global x1; upvar c x2; p3}
+    proc p3 {} {
+       upvar x1 a x2 b
+       list $a $b
+    }
+    p1 14 15
+} {88 22}
+test upvar-4.2 {nested upvars} {
+    set x1 88
+    proc p1 {a b} {set c 22; set d 33; p2; list $a $b $c $d}
+    proc p2 {} {global x1; upvar c x2; p3}
+    proc p3 {} {
+       upvar x1 a x2 b
+       set a foo
+       set b bar
+    }
+    list [p1 14 15] $x1
+} {{14 15 bar 33} foo}
+
+proc tproc {args} {global x; set x [list $args [uplevel info vars]]}
+
+test upvar-6.1 {retargeting an upvar} {
+    proc p1 {} {
+       set a(0) zeroth
+       set a(1) first
+       set a(2) second
+       p2
+    }
+    proc p2 {} {
+       upvar a x
+       set result {}
+       foreach i [array names x] {
+           upvar a($i) x
+           lappend result $x
+       }
+       lsort $result
+    }
+    p1
+} {first second zeroth}
+test upvar-6.2 {retargeting an upvar} {
+    set x 44
+    set y abcde
+    proc p1 {} {
+       global x
+       set result $x
+       upvar y x
+       lappend result $x
+    }
+    p1
+} {44 abcde}
+test upvar-6.3 {retargeting an upvar} {
+    set x 44
+    set y abcde
+    proc p1 {} {
+       upvar y x
+       lappend result $x
+       global x
+       lappend result $x
+    }
+    p1
+} {abcde 44}
+
+test upvar-7.1 {upvar to same level} {
+    set x 44
+    set y 55
+    catch {unset uv}
+    upvar #0 x uv
+    set uv abc
+    upvar 0 y uv
+    set uv xyzzy
+    list $x $y
+} {abc xyzzy}
+test upvar-7.2 {upvar to same level} {
+    set x 1234
+    set y 4567
+    proc p1 {x y} {
+       upvar 0 x uv
+       set uv $y
+       return "$x $y"
+    }
+    p1 44 89
+} {89 89}
+test upvar-7.3 {upvar to same level} {
+    set x 1234
+    set y 4567
+    proc p1 {x y} {
+       upvar #1 x uv
+       set uv $y
+       return "$x $y"
+    }
+    p1 xyz abc
+} {abc abc}
+test upvar-7.4 {upvar to same level: tricky problems when deleting variable table} {
+    proc tt {} {upvar #1 toto loc;  return $loc}
+    list [catch tt msg] $msg
+} {1 {can't read "loc": no such variable}}
+test upvar-7.5 {potential memory leak when deleting variable table} {
+    proc leak {} {
+       array set foo {1 2 3 4}
+       upvar 0 foo(1) bar
+    }
+    leak
+} {}
+
+test upvar-8.1 {errors in upvar command} {
+    catch upvar msg
+} 1
+test upvar-8.2 {errors in upvar command} {
+    catch {upvar 1}
+} 1
+test upvar-8.3 {errors in upvar command} {
+    proc p1 {} {upvar a b c}
+    catch p1
+} 1
+test upvar-8.4 {errors in upvar command} {
+    proc p1 {} {upvar 0 b b}
+    list [catch p1 msg] $msg
+} {1 {can't upvar from variable to itself}}
+test upvar-8.5 {errors in upvar command} {
+    proc p1 {} {upvar 0 a b; upvar 0 b a}
+    list [catch p1 msg] $msg
+} {1 {can't upvar from variable to itself}}
+test upvar-8.6 {errors in upvar command} {
+    proc p1 {} {set a 33; upvar b a}
+    list [catch p1 msg] $msg
+} {1 {variable "a" already exists}}
+# Jim allows dicts within dicts. Tcl can't do this.
+test upvar-8.8 {create nested array with upvar} jim {
+    proc p1 {} {upvar x(a) b; set b(2) 44}
+    catch {unset x}
+    p1
+    set x
+} {a {2 44}}
+test upvar-8.10 {upvar will create element alias for new array element} {
+    catch {unset upvarArray}
+    array set upvarArray {}
+    catch {upvar 0 upvarArray(elem) upvarArrayElemAlias}
+} {0}
+test upvar-8.11 {error upvar array element} {
+    proc a {} { upvar a b(1) }
+    list [catch {a} msg] $msg
+} {1 {bad variable name "b(1)": upvar won't create a scalar variable that looks like an array element}}
+test upvar-9.1 {global redefine} {
+    proc p1 {} { global x; global x }
+    p1
+} {}
+test upvar-9.2 {upvar redefine} {
+    set a 1
+    set b 2
+    proc p1 {} { upvar a x; upvar b x; return $x }
+    p1
+} 2
+test upvar-9.3 {upvar redefine static} jim {
+    proc p1 {} {{a 3}} { upvar b a; return $b }
+    list [catch p1 msg] $msg
+} {1 {variable "a" already exists}}
+test upvar-9.4 {upvar links to static} jim {
+    proc p1 {} {} { upvar a x; incr x; return $x }
+    proc p2 {} {{a 3}} { list [p1] $a }
+    p2
+} {4 4}
+test upvar-9.5 {upvar via global namespace} {
+    set x 2
+    unset -nocomplain y
+    # Links ::y to ::x
+    proc p1 {} { upvar x ::y; incr ::y -1 }
+    p1
+    list $x $y
+} {1 1}
+
+test upvar-9.6 {upvar via global namespace} {
+    set x 2
+    unset -nocomplain x
+    # Links ::x to ::x
+    proc p1 {} { upvar x ::x; incr ::x }
+    list [catch p1 msg] $msg
+} {1 {can't upvar from variable to itself}}
+
+test upvar-9.7 {upvar to higher level} {
+    proc p1 {} { upvar 0 x ::globx }
+    list [catch p1 msg] $msg
+} {1 {bad variable name "::globx": upvar won't create namespace variable that refers to procedure variable}}
+
+catch {unset a}
+
+testreport
diff --git a/jim/tests/utf8.test b/jim/tests/utf8.test
new file mode 100755 (executable)
index 0000000..74a5aa8
--- /dev/null
@@ -0,0 +1,152 @@
+source [file dirname [info script]]/testing.tcl
+
+needs constraint utf8
+
+test utf8-1.1 "Pattern matching - ?" {
+       string match "abc?def" "abc\u00b5def"
+} 1
+
+test utf8-1.2 "Pattern matching - ?" {
+       string match "abc?def" "abc\u2704def"
+} 1
+
+test utf8-1.3 "Pattern utf-8 literal" {
+       string match "ab\u00b5\u2704?" "ab\u00b5\u2704x" 
+} 1
+
+test utf8-1.4 "Pattern utf-8 char sets" {
+       string match "a\[b\u00b5\]\u2704?" "a\u00b5\u2704x" 
+} 1
+
+test utf8-1.5 "Pattern utf-8 char sets" {
+       string match "a\[b\u00b5\]\u2704?" "a\u00b6\u2704x" 
+} 0
+test utf8-1.6 "Pattern utf-8 char sets" {
+       string match "a\[b\u00b5\]\u2704?" "ab\u2704x" 
+} 1
+test utf8-1.7 "Pattern utf-8 char sets" {
+       string match "a\[b\u00b5\]?" "a\u2704x"
+} 0
+test utf8-1.8 "Pattern utf-8 char sets" {
+       string match "a\[\u00b5-\u00c3\]" "a\ubd"
+} 1
+test utf8-1.9 "Pattern utf-8 char sets" {
+       string match "a\[\u00b5-\u00c3\]" "a\uc4"
+} 0
+
+test utf8-2.1 "Pattern utf-8 nocase" {
+       string match -nocase "a\u1edc\u1ef4*" "A\u1edd\u1ef5XX"
+} 1
+
+test utf8-2.2 "Pattern utf-8 case difference" {
+       string match "a\u1edc\u1ef4*" "A\u1edd\u1ef5XX"
+} 0
+
+test utf8-3.1 "lsearch -glob" {
+       lsearch -glob {1 d a\u00b5xyb c} a\ub5*b
+} 2
+
+test utf8-3.2 "switch -glob" {
+       switch -glob -- a\ub5xyb a\ub5*b { set x 1 } default { set x 0 }
+       set x
+} 1
+
+set x "\ub5test"
+test utf8-3.3 "info procs" {
+       proc $x {} { info procs \[\ub5X]???? }
+       $x
+} $x
+
+test utf8-3.3 "info commands" {
+       info commands \[\ub5X]????
+} $x
+
+test utf8-3.4 "proc name with invalid utf-8" {
+       catch { proc ab\xc2 {} {} } msg
+} 0
+
+test utf8-3.5 "rename to invalid name" {
+       catch { rename ab\xc2 ab\xc3 } msg
+} 0
+
+catch {rename ab\xc3 ""}
+
+test utf8-4.1 "split with utf-8" {
+       split "zy\u2702xw" x
+} "zy\u2702 w"
+
+test utf8-4.2 "split with utf-8" {
+       split "zy\u2702xw" \u2702
+} "zy xw"
+
+test utf8-4.2 "split with utf-8" {
+       split "zy\u2702xw" {}
+} "z y \u2702 x w"
+
+test utf8-5.1 "string first with utf-8" {
+       string first w "zy\u2702xw"
+} 4
+
+test utf8-5.2 "string first with utf-8" {
+       string first \u2702 "\ub5zy\u2702xw"
+} 3
+
+test utf8-5.3 "string first with utf-8" {
+       string first \u2704 "\ub5zy\u2702xw"
+} -1
+
+test utf8-5.4 "string first with utf-8" {
+       string first \u2702 "\ub5zy\u2702xw\u2702BB"
+} 3
+
+test utf8-6.1 "string last with utf-8" {
+       string last w "zy\u2702xw"
+} 4
+
+test utf8-6.2 "string last with utf-8" {
+       string last \u2702 "\ub5zy\u2702xw"
+} 3
+
+test utf8-6.3 "string last with utf-8" {
+       string last \u2704 "\ub5zy\u2702xw"
+} -1
+
+test utf8-6.4 "string last with utf-8" {
+       string last \u2702 "\ub5zy\u2702xw\u2702BB"
+} 6
+
+test utf8-7.1 "string reverse" {
+       string reverse \ub5Test\u2702
+} \u2702tseT\ub5
+
+test utf8-7.2 {append counts correctly} {
+       set x \u2702XYZ
+       append x \u2702XYZ
+       list [string length $x] [string bytelength $x]
+} {8 12}
+
+test utf8-7.3 {Upper, lower for titlecase utf-8} {
+       list [string toupper \u01c5] [string tolower \u01c5]
+} "\u01c4 \u01c6"
+
+test utf8-7.4 {Case folding may change encoded length} {
+       list [string bytelength \u0131] [string bytelength [string toupper \u0131]]
+} {2 1}
+
+test utf8-8.1 {Chars outside the BMP} jim {
+       string length \u{12000}\u{13000}
+} 2
+
+test utf8-8.2 {Chars outside the BMP} jim {
+       string match "ab\[\u{12000}c\]d" ab\u{12000}d
+} 1
+
+test utf8-8.3 {Chars outside the BMP} jim {
+       string last d "ab\u{101fff}cd"
+} 4
+
+test utf8-8.4 {Longer sequences} {
+       string length \u12000
+} 2
+
+testreport
diff --git a/jim/tests/utftcl.test b/jim/tests/utftcl.test
new file mode 100755 (executable)
index 0000000..33b8933
--- /dev/null
@@ -0,0 +1,289 @@
+# This file contains a collection of tests for tclUtf.c
+# Sourcing this file into Tcl runs the tests and generates output for
+# errors.  No output means no errors were found.
+#
+# Copyright (c) 1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: utf.test,v 1.14 2007/05/02 01:37:28 kennykb Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+needs constraint utf8
+
+catch {unset x}
+
+test utf-1.1 {Tcl_UniCharToUtf: 1 byte sequences} {
+    set x \x01
+} [bytestring "\x01"]
+test utf-1.2 {Tcl_UniCharToUtf: 2 byte sequences} {
+    set x "\u80"
+} [bytestring "\xc2\x80"]
+test utf-1.3 {Tcl_UniCharToUtf: 2 byte sequences} {
+    set x "\ue0"
+} [bytestring "\xc3\xa0"]
+test utf-1.4 {Tcl_UniCharToUtf: 3 byte sequences} {
+    set x "\u4e4e"
+} [bytestring "\xe4\xb9\x8e"]
+test utf-1.5 {Tcl_UniCharToUtf: negative Tcl_UniChar} {
+    string length [format %c -1]
+} 1
+
+test utf-2.1 {Tcl_UtfToUniChar: low ascii} {
+    string length "abc"
+} {3}
+test utf-2.2 {Tcl_UtfToUniChar: naked trail bytes} {
+    string length [bytestring "\x82\x83\x84"]
+} {3}
+test utf-2.3 {Tcl_UtfToUniChar: lead (2-byte) followed by non-trail} {
+    string length [bytestring "\xC2"]
+} {1}
+test utf-2.4 {Tcl_UtfToUniChar: lead (2-byte) followed by trail} {
+    string length [bytestring "\xC2\xa2"]
+} {1}
+test utf-2.5 {Tcl_UtfToUniChar: lead (3-byte) followed by non-trail} {
+    string length [bytestring "\xE2"]
+} {1}
+test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} {
+    string length [bytestring "\xE2\xA2"]
+} {2}
+test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} {
+    string length [bytestring "\xE4\xb9\x8e"]
+} {1}
+# Note that Tcl may or may not support utf-8 sequences >= 4 bytes
+test utf-2.9 {Tcl_UtfToUniChar: 4-byte UTF sequence} {
+    string length [bytestring "\xF4\xA2\xA2\xA2"]
+} {1}
+
+test utf-3.1 {Tcl_UtfCharComplete} {
+} {}
+
+proc testnumutfchars {a {n ""}} {
+    string length $a
+}
+
+test utf-4.1 {Tcl_NumUtfChars: zero length} {
+    testnumutfchars ""
+} {0}
+test utf-4.2 {Tcl_NumUtfChars: length 1} {
+    testnumutfchars [bytestring "\xC2\xA2"]
+} {1}
+test utf-4.3 {Tcl_NumUtfChars: long string} {
+    testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"]
+} {7}
+test utf-4.4 {Tcl_NumUtfChars: #u0000} {
+    testnumutfchars [bytestring "\xC0\x80"]
+} {1}
+test utf-4.5 {Tcl_NumUtfChars: zero length, calc len} {
+    testnumutfchars "" 1
+} {0}
+test utf-4.6 {Tcl_NumUtfChars: length 1, calc len} {
+    testnumutfchars [bytestring "\xC2\xA2"] 1
+} {1}
+test utf-4.7 {Tcl_NumUtfChars: long string, calc len} {
+    testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] 1
+} {7}
+test utf-4.8 {Tcl_NumUtfChars: #u0000, calc len} {
+    testnumutfchars [bytestring "\xC0\x80"] 1
+} {1}
+
+test utf-5.1 {Tcl_UtfFindFirsts} {
+} {}
+
+test utf-6.1 {Tcl_UtfNext} {
+} {}
+
+test utf-7.1 {Tcl_UtfPrev} {
+} {}
+
+test utf-8.1 {Tcl_UniCharAtIndex: index = 0} {
+    string index abcd 0
+} {a}
+test utf-8.2 {Tcl_UniCharAtIndex: index = 0} {
+    string index \u4e4e\u25a 0
+} "\u4e4e"
+test utf-8.3 {Tcl_UniCharAtIndex: index > 0} {
+    string index abcd 2
+} {c}
+test utf-8.4 {Tcl_UniCharAtIndex: index > 0} {
+    string index \u4e4e\u25a\uff\u543 2
+} "\uff"
+
+test utf-9.1 {Tcl_UtfAtIndex: index = 0} {
+    string range abcd 0 2
+} {abc}
+test utf-9.2 {Tcl_UtfAtIndex: index > 0} {
+    string range \u4e4e\u25a\xff\u543klmnop 1 5
+} "\u25a\xff\u543kl"
+
+
+test utf-10.1 {Tcl_UtfBackslash: dst == NULL} {
+    set x \n
+} {
+}
+test utf-10.2 {Tcl_UtfBackslash: \u subst} {
+    set x \ua2
+} [bytestring "\xc2\xa2"]
+test utf-10.3 {Tcl_UtfBackslash: longer \u subst} {
+    set x \u4e21
+} [bytestring "\xe4\xb8\xa1"]
+test utf-10.4 {Tcl_UtfBackslash: stops at first non-hex} {
+    set x \u4e2k
+} "[bytestring \xd3\xa2]k"
+test utf-10.5 {Tcl_UtfBackslash: stops after 4 hex chars} {
+    set x \u4e216
+} "[bytestring \xe4\xb8\xa1]6"
+proc bsCheck {char num} {
+    global errNum
+    test utf-10.$errNum {backslash substitution} {
+       scan $char %c value
+       set value
+    } $num
+    incr errNum
+}
+set errNum 6
+bsCheck \b     8
+bsCheck \e     101
+bsCheck \f     12
+bsCheck \n     10
+bsCheck \r     13
+bsCheck \t     9
+bsCheck \v     11
+bsCheck \{     123
+bsCheck \}     125
+bsCheck \[     91
+bsCheck \]     93
+bsCheck \$     36
+bsCheck \      32
+bsCheck \;     59
+bsCheck \\     92
+bsCheck \Ca    67
+bsCheck \Ma    77
+bsCheck \CMa   67
+# prior to 8.3, this returned 8, as \8 as accepted as an
+# octal value - but it isn't! [Bug: 3975]
+bsCheck \8a    56
+bsCheck \14    12
+bsCheck \141   97
+bsCheck b\0    98
+bsCheck \x     120
+bsCheck \ua    10
+bsCheck \uA    10
+bsCheck \u41   65
+bsCheck \u     117
+bsCheck \uk    117
+bsCheck \u41   65
+bsCheck \ua    10
+bsCheck \uA    10
+bsCheck \340   224
+bsCheck \ua1   161
+bsCheck \u4e21 20001
+
+test utf-11.1 {Tcl_UtfToUpper} {
+    string toupper {}
+} {}
+test utf-11.2 {Tcl_UtfToUpper} {
+    string toupper abc
+} ABC
+test utf-11.3 {Tcl_UtfToUpper} {
+    string toupper \u00e3ab
+} \u00c3AB
+test utf-11.4 {Tcl_UtfToUpper} {
+    string toupper \u01e3ab
+} \u01e2AB
+
+test utf-12.1 {Tcl_UtfToLower} {
+    string tolower {}
+} {}
+test utf-12.2 {Tcl_UtfToLower} {
+    string tolower ABC
+} abc
+test utf-12.3 {Tcl_UtfToLower} {
+    string tolower \u00c3AB
+} \u00e3ab
+test utf-12.4 {Tcl_UtfToLower} {
+    string tolower \u01e2AB
+} \u01e3ab
+
+
+test utf-14.1 {Tcl_UtfNcasecmp} {
+    string compare -nocase a b
+} -1
+test utf-14.2 {Tcl_UtfNcasecmp} {
+    string compare -nocase b a
+} 1
+test utf-14.3 {Tcl_UtfNcasecmp} {
+    string compare -nocase B a
+} 1
+test utf-14.4 {Tcl_UtfNcasecmp} {
+    string compare -nocase aBcB abca
+} 1
+
+test utf-15.1 {Tcl_UniCharToUpper, negative delta} {
+    string toupper aA
+} AA
+test utf-15.2 {Tcl_UniCharToUpper, positive delta} {
+    string toupper \u0178\u00ff
+} \u0178\u0178
+test utf-15.3 {Tcl_UniCharToUpper, no delta} {
+    string toupper !
+} !
+
+test utf-16.1 {Tcl_UniCharToLower, negative delta} {
+    string tolower aA
+} aa
+test utf-16.2 {Tcl_UniCharToLower, positive delta} {
+    string tolower \u0178\u00ff
+} \u00ff\u00ff
+test utf-17.1 {Tcl_UniCharToLower, no delta} {
+    string tolower !
+} !
+
+
+#test utf-21.1 {TclUniCharIsAlnum} {
+#    # this returns 1 with Unicode 3 compliance
+#    string is alnum \u1040\u021f
+#} {1}
+#test utf-21.2 {unicode alnum char in regc_locale.c} {
+#    # this returns 1 with Unicode 3 compliance
+#    list [regexp {^[[:alnum:]]+$} \u1040\u021f] [regexp {^\w+$} \u1040\u021f]
+#} {1 1}
+
+#test utf-22.1 {TclUniCharIsWordChar} {
+#    string wordend "xyz123_bar fg" 0
+#} 10
+#test utf-22.2 {TclUniCharIsWordChar} {
+#    string wordend "x\u5080z123_bar\u203c fg" 0
+#} 10
+
+#test utf-23.1 {TclUniCharIsAlpha} {
+#    # this returns 1 with Unicode 3 compliance
+#    string is alpha \u021f
+#} {1}
+#test utf-23.2 {unicode alpha char in regc_locale.c} {
+#    # this returns 1 with Unicode 3 compliance
+#    regexp {^[[:alpha:]]+$} \u021f
+#} {1}
+#
+#test utf-24.1 {TclUniCharIsDigit} {
+#    # this returns 1 with Unicode 3 compliance
+#    string is digit \u1040
+#} {1}
+#test utf-24.2 {unicode digit char in regc_locale.c} {
+#    # this returns 1 with Unicode 3 compliance
+#    list [regexp {^[[:digit:]]+$} \u1040] [regexp {^\d+$} \u1040]
+#} {1 1}
+#
+#test utf-24.3 {TclUniCharIsSpace} {
+#    # this returns 1 with Unicode 3 compliance
+#    string is space \u1680
+#} {1}
+#test utf-24.4 {unicode space char in regc_locale.c} {
+#    # this returns 1 with Unicode 3 compliance
+#    list [regexp {^[[:space:]]+$} \u1680] [regexp {^\s+$} \u1680]
+#} {1 1}
+
+testreport
diff --git a/jim/tests/util.test b/jim/tests/util.test
new file mode 100755 (executable)
index 0000000..6b54425
--- /dev/null
@@ -0,0 +1,481 @@
+# This file is a Tcl script to test the code in the file tclUtil.c.
+# This file is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1995-1998 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+source [file dirname [info script]]/testing.tcl
+
+needs cmd binary
+testConstraint controversialNaN 1
+testConstraint testdstring [llength [info commands testdstring]]
+testConstraint testconcatobj [llength [info commands testconcatobj]]
+
+# Big test for correct ordering of data in [expr]
+
+proc convertDouble { x } {
+    variable ieeeValues
+    if { $ieeeValues(littleEndian) } {
+       binary scan [binary format w $x] d result
+    } else {
+       binary scan [binary format W $x] d result
+    }
+    return $result
+}
+
+test util-1.1 {TclFindElement procedure - binary element in middle of list} {
+    lindex {0 foo\x00help 1} 1
+} "foo\x00help"
+test util-1.2 {TclFindElement procedure - binary element at end of list} {
+    lindex {0 foo\x00help} 1
+} "foo\x00help"
+
+test util-2.1 {TclCopyAndCollapse procedure - normal string} {
+    lindex {0 foo} 1
+} {foo}
+test util-2.2 {TclCopyAndCollapse procedure - string with backslashes} {
+    lindex {0 foo\n\x00help 1} 1
+} "foo\n\x00help"
+
+test util-3.1 {Tcl_ScanCountedElement procedure - don't leave unmatched braces} {
+    # This test checks for a very tricky feature.  Any list element
+    # generated with Tcl_ScanCountedElement and Tcl_ConvertElement must
+    # have the property that it can be enclosing in curly braces to make
+    # an embedded sub-list.  If this property doesn't hold, then
+    # Tcl_DStringStartSublist doesn't work.
+    set x {}
+    lappend x "# \\\{ \\"
+    concat $x [llength "{$x}"]
+} {\#\ \\\{\ \\ 1}
+test util-3.2 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+    list # # a
+} {{#} # a}
+test util-3.3 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+    list #\{ # a
+} {\#\{ # a}
+test util-3.4 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+    proc # {} {return #}
+    set result [eval [list #]]
+    rename # {}
+    set result
+} {#}
+test util-3.4.1 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+    proc # {} {return #}
+    set cmd [list #]
+    append cmd ""      ;# force string rep generation
+    set result [eval $cmd]
+    rename # {}
+    set result
+} {#}
+test util-3.5 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+    proc #\{ {} {return #}
+    set result [eval [list #\{]]
+    rename #\{ {}
+    set result
+} {#}
+test util-3.5.1 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+    proc #\{ {} {return #}
+    set cmd [list #\{]
+    append cmd ""      ;# force string rep generation
+    set result [eval $cmd]
+    rename #\{ {}
+    set result
+} {#}
+test util-3.6 {Tcl_ConvertElement, Bug 3371644} tcl {
+    interp create #\\
+    interp alias {} x #\\ concat
+    interp target {} x ;# Crash if bug not fixed
+    interp delete #\\
+} {}
+
+test util-4.1 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b\ } c
+} {a b\  c}
+test util-4.2 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b\   } c
+} {a b\  c}
+test util-4.3 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b\\   } c
+} {a b\\  c}
+test util-4.4 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a {b } c
+} {a b c}
+test util-4.5 {Tcl_ConcatObj - backslash-space at end of argument} {
+    concat a { } c
+} {a c}
+test util-4.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} {
+    # Check for Bug #227512.  If this violates C isspace, then it returns \xc3.
+    concat \xe0
+} \xe0
+test util-4.7 {Tcl_ConcatObj - refCount safety} testconcatobj {
+    # Check for Bug #1447328 (actually, bugs in its original "fix"). One of the
+    # symptoms was Bug #2055782. 
+    testconcatobj
+} {}
+
+proc Wrapper_Tcl_StringMatch {pattern string} {
+    # Forces use of Tcl_StringMatch, not Tcl_UniCharCaseMatch
+    switch -glob -- $string $pattern {return 1} default {return 0}
+}
+test util-5.1 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch ab*c abc
+} 1
+test util-5.2 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch ab**c abc
+} 1
+test util-5.3 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch ab* abcdef
+} 1
+test util-5.4 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch *c abc
+} 1
+test util-5.5 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch *3*6*9 0123456789
+} 1
+test util-5.6 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch *3*6*9 01234567890
+} 0
+test util-5.7 {Tcl_StringMatch: UTF-8} {
+    Wrapper_Tcl_StringMatch *u \u4e4fu
+} 1
+test util-5.8 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch a?c abc
+} 1
+test util-5.9 {Tcl_StringMatch: UTF-8} utf8 {
+    # skip one character in string
+    Wrapper_Tcl_StringMatch a?c a\u4e4fc
+} 1
+test util-5.10 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch a??c abc
+} 0
+test util-5.11 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch ?1??4???8? 0123456789
+} 1
+test util-5.12 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {[abc]bc} abc
+} 1
+test util-5.13 {Tcl_StringMatch: UTF-8} utf8 {
+    # string += Tcl_UtfToUniChar(string, &ch);
+    Wrapper_Tcl_StringMatch "\[\u4e4fxy\]bc" "\u4e4fbc"
+} 1
+test util-5.14 {Tcl_StringMatch} {
+    # if ((*pattern == ']') || (*pattern == '\0'))
+    # badly formed pattern
+    Wrapper_Tcl_StringMatch {[]} {[]}
+} 0
+test util-5.15 {Tcl_StringMatch} {
+    # if ((*pattern == ']') || (*pattern == '\0'))
+    # badly formed pattern
+    Wrapper_Tcl_StringMatch {[} {[}
+} 0
+test util-5.16 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {a[abc]c} abc
+} 1
+test util-5.17 {Tcl_StringMatch: UTF-8} utf8 {
+    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
+    # get 1 UTF-8 character
+    Wrapper_Tcl_StringMatch "a\[a\u4e4fc]c" "a\u4e4fc"
+} 1
+test util-5.18 {Tcl_StringMatch: UTF-8} {
+    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
+    # proper advance: wrong answer would match on UTF trail byte of \u4e4f
+    Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} [bytestring a\u008fc]
+} 0
+test util-5.19 {Tcl_StringMatch: UTF-8} {
+    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
+    # proper advance.
+    Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} "acc"
+} 1
+test util-5.20 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {a[xyz]c} abc
+} 0
+test util-5.21 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {12[2-7]45} 12345
+} 1
+test util-5.22 {Tcl_StringMatch: UTF-8 range} {
+    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "0"
+} 0
+test util-5.23 {Tcl_StringMatch: UTF-8 range} utf8 {
+    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\u4e33"
+} 1
+test util-5.24 {Tcl_StringMatch: UTF-8 range} utf8 {
+    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\uff08"
+} 0
+test util-5.25 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12345
+} 1
+test util-5.26 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12b45
+} 1
+test util-5.27 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12d45
+} 1
+test util-5.28 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12145
+} 0
+test util-5.29 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12545
+} 0
+test util-5.30 {Tcl_StringMatch: forwards range} {
+    Wrapper_Tcl_StringMatch {[k-w]} "z"
+} 0
+test util-5.31 {Tcl_StringMatch: forwards range} {
+    Wrapper_Tcl_StringMatch {[k-w]} "w"
+} 1
+test util-5.32 {Tcl_StringMatch: forwards range} {
+    Wrapper_Tcl_StringMatch {[k-w]} "r"
+} 1
+test util-5.33 {Tcl_StringMatch: forwards range} {
+    Wrapper_Tcl_StringMatch {[k-w]} "k"
+} 1
+test util-5.34 {Tcl_StringMatch: forwards range} {
+    Wrapper_Tcl_StringMatch {[k-w]} "a"
+} 0
+test util-5.35 {Tcl_StringMatch: reverse range} {
+    Wrapper_Tcl_StringMatch {[w-k]} "z"
+} 0
+test util-5.36 {Tcl_StringMatch: reverse range} {
+    Wrapper_Tcl_StringMatch {[w-k]} "w"
+} 1
+test util-5.37 {Tcl_StringMatch: reverse range} {
+    Wrapper_Tcl_StringMatch {[w-k]} "r"
+} 1
+test util-5.38 {Tcl_StringMatch: reverse range} {
+    Wrapper_Tcl_StringMatch {[w-k]} "k"
+} 1
+test util-5.39 {Tcl_StringMatch: reverse range} {
+    Wrapper_Tcl_StringMatch {[w-k]} "a"
+} 0
+test util-5.40 {Tcl_StringMatch: skip correct number of ']'} {
+    Wrapper_Tcl_StringMatch {[A-]x} Ax
+} 0
+test util-5.41 {Tcl_StringMatch: skip correct number of ']'} {
+    Wrapper_Tcl_StringMatch {[A-]]x} Ax
+} 1
+test util-5.42 {Tcl_StringMatch: skip correct number of ']'} {
+    Wrapper_Tcl_StringMatch {[A-]]x} \ue1x
+} 0
+test util-5.43 {Tcl_StringMatch: skip correct number of ']'} utf8 {
+    Wrapper_Tcl_StringMatch \[A-]\ue1]x \ue1x
+} 1
+test util-5.44 {Tcl_StringMatch: skip correct number of ']'} {
+    Wrapper_Tcl_StringMatch {[A-]h]x} hx
+} 1
+test util-5.45 {Tcl_StringMatch} {
+    # if (*pattern == '\0')
+    # badly formed pattern, still treats as a set
+    Wrapper_Tcl_StringMatch {[a} a
+} 1
+test util-5.46 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {a\*b} a*b
+} 1
+test util-5.47 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {a\*b} ab
+} 0
+test util-5.48 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch {a\*\?\[\]\\\x} "a*?\[\]\\x"
+} 1
+test util-5.49 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch ** ""
+} 1
+test util-5.50 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch *. ""
+} 0
+test util-5.51 {Tcl_StringMatch} {
+    Wrapper_Tcl_StringMatch "" ""
+} 1
+
+test util-9.0.0 {TclGetIntForIndex} {
+    string index abcd 0
+} a
+test util-9.0.1 {TclGetIntForIndex} {
+    string index abcd 0x0
+} a
+test util-9.0.2 {TclGetIntForIndex} {
+    string index abcd -0x0
+} a
+test util-9.0.3 {TclGetIntForIndex} {
+    string index abcd { 0 }
+} a
+test util-9.0.4 {TclGetIntForIndex} {
+    string index abcd { 0x0 }
+} a
+test util-9.0.5 {TclGetIntForIndex} {
+    string index abcd { -0x0 }
+} a
+test util-9.0.6 {TclGetIntForIndex} {
+    string index abcd 01
+} b
+test util-9.0.7 {TclGetIntForIndex} {
+    string index abcd { 01 }
+} b
+test util-9.1.0 {TclGetIntForIndex} {
+    string index abcd 3
+} d
+test util-9.1.1 {TclGetIntForIndex} {
+    string index abcd { 3 }
+} d
+test util-9.1.2 {TclGetIntForIndex} {
+    string index abcdefghijk 0xa
+} k
+test util-9.1.3 {TclGetIntForIndex} {
+    string index abcdefghijk { 0xa }
+} k
+test util-9.2.0 {TclGetIntForIndex} {
+    string index abcd end
+} d 
+test util-9.2.1 {TclGetIntForIndex} -body {
+    string index abcd { end}
+} -returnCodes error -match glob -result *
+test util-9.2.2 {TclGetIntForIndex} -constraints tcl -body {
+    string index abcd {end }
+} -returnCodes error -match glob -result *
+test util-9.3 {TclGetIntForIndex} tcl {
+    # Deprecated
+    string index abcd en
+} d
+test util-9.4 {TclGetIntForIndex} tcl {
+    # Deprecated
+    string index abcd e
+} d
+test util-9.5.0 {TclGetIntForIndex} {
+    string index abcd end-1
+} c
+test util-9.5.1 {TclGetIntForIndex} tcl {
+    string index abcd {end-1 }
+} c
+test util-9.5.2 {TclGetIntForIndex} -body {
+    string index abcd { end-1}
+} -returnCodes error -match glob -result *
+test util-9.6 {TclGetIntForIndex} {
+    string index abcd end+-1
+} c
+test util-9.7 {TclGetIntForIndex} {
+    string index abcd end+1
+} {}
+test util-9.8 {TclGetIntForIndex} {
+    string index abcd end--1
+} {}
+test util-9.9.0 {TclGetIntForIndex} {
+    string index abcd 0+0
+} a
+test util-9.9.1 {TclGetIntForIndex} tcl {
+    string index abcd { 0+0 }
+} a
+test util-9.10 {TclGetIntForIndex} {
+    string index abcd 0-0
+} a
+test util-9.11 {TclGetIntForIndex} {
+    string index abcd 1+0
+} b
+test util-9.12 {TclGetIntForIndex} {
+    string index abcd 1-0
+} b
+test util-9.13 {TclGetIntForIndex} {
+    string index abcd 1+1
+} c
+test util-9.14 {TclGetIntForIndex} {
+    string index abcd 1-1
+} a
+test util-9.15 {TclGetIntForIndex} {
+    string index abcd -1+2
+} b
+test util-9.16 {TclGetIntForIndex} {
+    string index abcd -1--2
+} b
+test util-9.17 {TclGetIntForIndex} tcl {
+    string index abcd { -1+2 }
+} b
+test util-9.18 {TclGetIntForIndex} tcl {
+    string index abcd { -1--2 }
+} b
+test util-9.19 {TclGetIntForIndex} -body {
+    string index a {}
+} -returnCodes error -match glob -result *
+test util-9.20 {TclGetIntForIndex} -body {
+    string index a { }
+} -returnCodes error -match glob -result *
+test util-9.21 {TclGetIntForIndex} -body {
+    string index a " \r\t\n"
+} -returnCodes error -match glob -result *
+test util-9.22 {TclGetIntForIndex} -body {
+    string index a +
+} -returnCodes error -match glob -result *
+test util-9.23 {TclGetIntForIndex} -body {
+    string index a -
+} -returnCodes error -match glob -result *
+test util-9.24 {TclGetIntForIndex} -body {
+    string index a x
+} -returnCodes error -match glob -result *
+test util-9.25 {TclGetIntForIndex} -body {
+    string index a +x
+} -returnCodes error -match glob -result *
+test util-9.26 {TclGetIntForIndex} -body {
+    string index a -x
+} -returnCodes error -match glob -result *
+test util-9.27 {TclGetIntForIndex} -body {
+    string index a 0y
+} -returnCodes error -match glob -result *
+test util-9.28 {TclGetIntForIndex} -body {
+    string index a 1*
+} -returnCodes error -match glob -result *
+test util-9.29 {TclGetIntForIndex} -body {
+    string index a 0+
+} -returnCodes error -match glob -result *
+test util-9.30 {TclGetIntForIndex} -body {
+    string index a {0+ }
+} -returnCodes error -match glob -result *
+test util-9.31 {TclGetIntForIndex} -body {
+    string index a 0x
+} -returnCodes error -match glob -result *
+test util-9.32 {TclGetIntForIndex} -constraints tcl -body {
+    string index a 0x1FFFFFFFF+0
+} -returnCodes error -match glob -result *
+test util-9.33 {TclGetIntForIndex} -constraints tcl -body {
+    string index a 100000000000+0
+} -returnCodes error -match glob -result *
+test util-9.34 {TclGetIntForIndex} -body {
+    string index a 1.0
+} -returnCodes error -match glob -result *
+test util-9.35 {TclGetIntForIndex} -body {
+    string index a 1e23
+} -returnCodes error -match glob -result *
+test util-9.36 {TclGetIntForIndex} -body {
+    string index a 1.5e2
+} -returnCodes error -match glob -result *
+test util-9.37 {TclGetIntForIndex} -body {
+    string index a 0+x
+} -returnCodes error -match glob -result *
+test util-9.38 {TclGetIntForIndex} -body {
+    string index a 0+0x
+} -returnCodes error -match glob -result *
+test util-9.39 {TclGetIntForIndex} -body {
+    string index a 0+0xg
+} -returnCodes error -match glob -result *
+test util-9.40 {TclGetIntForIndex} -body {
+    string index a 0+0xg
+} -returnCodes error -match glob -result *
+test util-9.41 {TclGetIntForIndex} -body {
+    string index a 0+1.0
+} -returnCodes error -match glob -result *
+test util-9.42 {TclGetIntForIndex} -body {
+    string index a 0+1e2
+} -returnCodes error -match glob -result *
+test util-9.43 {TclGetIntForIndex} -body {
+    string index a 0+1.5e1
+} -returnCodes error -match glob -result *
+test util-9.44 {TclGetIntForIndex} -constraints tcl -body {
+    string index a 0+1000000000000
+} -returnCodes error -match glob -result *
+
+
+# cleanup
+::tcltest::cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/jim/tests/while.test b/jim/tests/while.test
new file mode 100755 (executable)
index 0000000..de6d9b5
--- /dev/null
@@ -0,0 +1,127 @@
+# Commands covered:  while
+#
+# This file contains the original set of tests for Tcl's while command.
+# Since the while command is now compiled, a new set of tests covering
+# the new implementation is in the file "while.test". Sourcing this file
+# into Tcl runs the tests and generates output for errors.
+# No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: while-old.test,v 1.6 2000/04/10 17:19:06 ericm Exp $
+
+source [file dirname [info script]]/testing.tcl
+
+test while-old-1.1 {basic while loops} {
+    set count 0
+    while {$count < 10} {set count [expr $count+1]}
+    set count
+} 10
+test while-old-1.2 {basic while loops} {
+    set value xxx
+    while {2 > 3} {set value yyy}
+    set value
+} xxx
+test while-old-1.3 {basic while loops} {
+    set value 1
+    while {1} {
+       incr value;
+       if {$value > 5} {
+           break;
+       }
+    }
+    set value
+} 6
+test while-old-1.4 {basic while loops, multiline test expr} {
+    set value 1
+    while {($tcl_platform(platform) != "foobar1") && \
+           ($tcl_platform(platform) != "foobar2")} {
+        incr value
+        break
+    }
+    set value
+} {2}
+test while-old-1.5 {basic while loops, test expr in quotes} {
+    set value 1
+    while "0 < 3" {set value 2; break}
+    set value
+} {2}
+
+test while-old-2.1 {continue in while loop} {
+    set list {1 2 3 4 5}
+    set index 0
+    set result {}
+    while {$index < 5} {
+       if {$index == 2} {set index [expr $index+1]; continue}
+       set result [concat $result [lindex $list $index]]
+       set index [expr $index+1]
+    }
+    set result
+} {1 2 4 5}
+
+test while-old-3.1 {break in while loop} {
+    set list {1 2 3 4 5}
+    set index 0
+    set result {}
+    while {$index < 5} {
+       if {$index == 3} break
+       set result [concat $result [lindex $list $index]]
+       set index [expr $index+1]
+    }
+    set result
+} {1 2 3}
+
+test while-old-4.1 {errors in while loops} {
+    set err [catch {while} msg]
+    list $err
+} {1}
+test while-old-4.2 {errors in while loops} {
+    set err [catch {while 1} msg]
+    list $err
+} {1}
+test while-old-4.3 {errors in while loops} {
+    set err [catch {while 1 2 3} msg]
+    list $err
+} {1}
+test while-old-4.4 {errors in while loops} {
+    set err [catch {while {"a"+"b"} {error "loop aborted"}} msg]
+    list $err
+} {1}
+test while-old-4.5 {errors in while loops} {
+    catch {unset x}
+    set x 1
+    set err [catch {while {$x} {set x foo}} msg]
+    list $err
+} {1}
+test while-old-4.6 {errors in while loops} {
+    set err [catch {while {1} {error "loop aborted"}} msg]
+    list $err $msg
+} {1 {loop aborted}}
+
+test while-old-5.1 {while return result} {
+    while {0} {set a 400}
+} {}
+test while-old-5.2 {while return result} {
+    set x 1
+    while {$x} {set x 0}
+} {}
+
+# cleanup
+testreport
+
+
+
+
+
+
+
+
+
+
+
+
old mode 100644 (file)
new mode 100755 (executable)
index 01fc167..d897c51
@@ -29,11 +29,11 @@ package require oo
 # $pt get <nodename> <key>
 #
 #   Returns the value associated with the given key
-# 
+#
 # $pt getall <nodename>
 #
 #   Returns the entire attribute dictionary associated with the given key
-# 
+#
 # $pt depth <nodename>
 #
 #   Returns the depth of the given node. The depth of "root" is 0.
@@ -41,19 +41,19 @@ package require oo
 # $pt parent <nodename>
 #
 #   Returns the name of the parent node, or "" for the root node.
-# 
+#
 # $pt numchildren <nodename>
 #
 #   Returns the number of child nodes.
-# 
+#
 # $pt children <nodename>
 #
 #   Returns a list of the child nodes.
-# 
+#
 # $pt next <nodename>
 #
 #   Returns the next sibling node, or "" if none.
-# 
+#
 # $pt insert <nodename> ?index?
 #
 #   Add a new child node to the given node.
index a81b3de..603e8ac 100644 (file)
@@ -14,7 +14,7 @@
 #include "utf8.h"
 
 /* This one is always implemented */
-int utf8_fromunicode(char *p, unsigned short uc)
+int utf8_fromunicode(char *p, unsigned uc)
 {
     if (uc <= 0x7f) {
         *p = uc;
@@ -25,12 +25,20 @@ int utf8_fromunicode(char *p, unsigned short uc)
         *p = 0x80 | (uc & 0x3f);
         return 2;
     }
-    else {
+    else if (uc <= 0xffff) {
         *p++ = 0xe0 | ((uc & 0xf000) >> 12);
         *p++ = 0x80 | ((uc & 0xfc0) >> 6);
         *p = 0x80 | (uc & 0x3f);
         return 3;
     }
+    /* Note: We silently truncate to 21 bits here: 0x1fffff */
+    else {
+        *p++ = 0xf0 | ((uc & 0x1c0000) >> 18);
+        *p++ = 0x80 | ((uc & 0x3f000) >> 12);
+        *p++ = 0x80 | ((uc & 0xfc0) >> 6);
+        *p = 0x80 | (uc & 0x3f);
+        return 4;
+    }
 }
 
 #if defined(JIM_UTF8) && !defined(JIM_BOOTSTRAP)
@@ -78,16 +86,6 @@ int utf8_index(const char *str, int index)
     return s - str;
 }
 
-int utf8_charequal(const char *s1, const char *s2)
-{
-    int c1, c2;
-
-    utf8_tounicode(s1, &c1);
-    utf8_tounicode(s2, &c2);
-
-    return c1 == c2;
-}
-
 int utf8_prev_len(const char *str, int len)
 {
     int n = 1;
@@ -129,6 +127,12 @@ int utf8_tounicode(const char *str, int *uc)
             return 3;
         }
     }
+    else if (s[0] < 0xf8) {
+        if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80) && ((str[3] & 0xc0) == 0x80)) {
+            *uc = ((s[0] & ~0xf0) << 18) | ((s[1] & ~0x80) << 12) | ((s[2] & ~0x80) << 6) | (s[3] & ~0x80);
+            return 4;
+        }
+    }
 
     /* Invalid sequence, so just return the byte */
     *uc = *s;
@@ -136,57 +140,62 @@ int utf8_tounicode(const char *str, int *uc)
 }
 
 struct casemap {
-    unsigned short code;    /* code point */
-    signed char lowerdelta; /* add for lowercase, or if -128 use the ext table */
-    signed char upperdelta; /* add for uppercase, or offset into the ext table */
-};
-
-/* Extended table for codepoints where |delta| > 127 */
-struct caseextmap {
-    unsigned short lower;
-    unsigned short upper;
+    unsigned short code;        /* code point */
+    unsigned short altcode;     /* alternate case code point */
 };
 
 /* Generated mapping tables */
 #include "_unicode_mapping.c"
 
-#define NUMCASEMAP sizeof(unicode_case_mapping) / sizeof(*unicode_case_mapping)
+#define ARRAYSIZE(A) sizeof(A) / sizeof(*(A))
 
 static int cmp_casemap(const void *key, const void *cm)
 {
     return *(int *)key - (int)((const struct casemap *)cm)->code;
 }
 
-static int utf8_map_case(int uc, int upper)
+static int utf8_map_case(const struct casemap *mapping, int num, int ch)
 {
-    const struct casemap *cm = bsearch(&uc, unicode_case_mapping, NUMCASEMAP, sizeof(*unicode_case_mapping), cmp_casemap);
+    /* We only support 16 bit case mapping */
+    if (ch <= 0xffff) {
+        const struct casemap *cm =
+            bsearch(&ch, mapping, num, sizeof(*mapping), cmp_casemap);
 
-    if (cm) {
-        if (cm->lowerdelta == -128) {
-            uc = upper ? unicode_extmap[cm->upperdelta].upper : unicode_extmap[cm->upperdelta].lower;
-        }
-        else {
-            uc += upper ? cm->upperdelta : cm->lowerdelta;
+        if (cm) {
+            return cm->altcode;
         }
     }
-    return uc;
+    return ch;
 }
 
-int utf8_upper(int uc)
+/* Some platforms don't have isascii */
+#ifndef isascii
+#define isascii(C) (!((C) & ~0x7f))
+#endif
+
+int utf8_upper(int ch)
 {
-    if (isascii(uc)) {
-        return toupper(uc);
+    if (isascii(ch)) {
+        return toupper(ch);
     }
-    return utf8_map_case(uc, 1);
+    return utf8_map_case(unicode_case_mapping_upper, ARRAYSIZE(unicode_case_mapping_upper), ch);
 }
 
-int utf8_lower(int uc)
+int utf8_lower(int ch)
 {
-    if (isascii(uc)) {
-        return tolower(uc);
+    if (isascii(ch)) {
+        return tolower(ch);
     }
+    return utf8_map_case(unicode_case_mapping_lower, ARRAYSIZE(unicode_case_mapping_lower), ch);
+}
 
-    return utf8_map_case(uc, 0);
+int utf8_title(int ch)
+{
+    int newch = utf8_map_case(unicode_case_mapping_title, ARRAYSIZE(unicode_case_mapping_title), ch);
+    if (newch != ch) {
+        return newch ? newch : ch;
+    }
+    return utf8_upper(ch);
 }
 
 #endif /* JIM_BOOTSTRAP */
index 9ada93f..7288113 100644 (file)
@@ -1,5 +1,10 @@
 #ifndef UTF8_UTIL_H
 #define UTF8_UTIL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * UTF-8 utility functions
  *
  */
 #include <jim-config.h>
 
+/* Currently we support unicode points up to 2^22-1 */
+#define MAX_UTF8_LEN 4
+
 /**
- * Converts the given unicode codepoint (0 - 0xffff) to utf-8
+ * Converts the given unicode codepoint (0 - 0x1fffff) to utf-8
  * and stores the result at 'p'.
  *
- * Returns the number of utf-8 characters (1-3).
+ * Returns the number of utf-8 characters (up to MAX_UTF8_LEN).
  */
-int utf8_fromunicode(char *p, unsigned short uc);
+int utf8_fromunicode(char *p, unsigned uc);
 
 #ifndef JIM_UTF8
 #include <ctype.h>
@@ -23,7 +31,9 @@ int utf8_fromunicode(char *p, unsigned short uc);
 /* No utf-8 support. 1 byte = 1 char */
 #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B))
 #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1)
+#define utf8_getchars(CP, C) (*(CP) = (C), 1)
 #define utf8_upper(C) toupper(C)
+#define utf8_title(C) toupper(C)
 #define utf8_lower(C) tolower(C)
 #define utf8_index(C, I) (I)
 #define utf8_charlen(C) 1
@@ -31,6 +41,9 @@ int utf8_fromunicode(char *p, unsigned short uc);
 
 #else
 #if !defined(JIM_BOOTSTRAP)
+
+#define utf8_getchars utf8_fromunicode
+
 /**
  * Returns the length of the utf-8 sequence starting with 'c'.
  *
@@ -49,7 +62,7 @@ int utf8_charlen(int c);
  *
  * The string *must* be null terminated.
  *
- * Does not support unicode code points > \uffff
+ * Does not support unicode code points > \u1fffff
  */
 int utf8_strlen(const char *str, int bytelen);
 
@@ -75,7 +88,7 @@ int utf8_index(const char *str, int charindex);
  *
  * If it is not null terminated, the length *must* be checked first.
  *
- * Does not support unicode code points > \uffff
+ * Does not support unicode code points > \u1fffff
  */
 int utf8_tounicode(const char *str, int *uc);
 
@@ -91,20 +104,33 @@ int utf8_prev_len(const char *str, int len);
 /**
  * Returns the upper-case variant of the given unicode codepoint.
  *
- * Does not support unicode code points > \uffff
+ * Unicode code points > \uffff are returned unchanged.
  */
 int utf8_upper(int uc);
 
 /**
+ * Returns the title-case variant of the given unicode codepoint.
+ *
+ * If none, returns utf8_upper().
+ *
+ * Unicode code points > \uffff are returned unchanged.
+ */
+int utf8_title(int uc);
+
+/**
  * Returns the lower-case variant of the given unicode codepoint.
  *
  * NOTE: Use utf8_upper() in preference for case-insensitive matching.
  *
- * Does not support unicode code points > \uffff
+ * Unicode code points > \uffff are returned unchanged.
  */
 int utf8_lower(int uc);
 #endif /* JIM_BOOTSTRAP */
 
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index e0c46dc..2fef0cf 100644 (file)
@@ -1,7 +1,7 @@
 Name:       usb-modeswitch
 Summary:    USB Modeswitch gets mobile broadband cards in operational mode
-Version:    2.2.6
-Release:    2
+Version:    2.2.1
+Release:    6
 Group:      System/Tools
 License:    GPL-2.0
 URL:        http://www.draisberghof.de/usb_modeswitch/
@@ -9,12 +9,7 @@ Source0:    %{name}-%{version}.tar.gz
 BuildRequires:  pkgconfig(libusb-1.0)
 Requires:       usb-modeswitch-data
 
-# This package would be built only TV
-%if "%{?tizen_profile_name}" != "tv"
-ExcludeArch: %{arm} %ix86 x86_64
-%endif
-
-%if "%{?_repository}" == "emulator"
+%if "%{_with_emulator}" == "1"
 ExcludeArch: %{arm} %ix86 x86_64
 %endif
 
old mode 100644 (file)
new mode 100755 (executable)
index 5bf0685..b69d2cd
@@ -113,9 +113,8 @@ Send a special control message used by the MobileAction device
 Send a special control message used by Qisda devices
 .IP "\fB-E\fP \fB\-\-quanta-mode\fP         " 10
 Send a special control message used by Quanta devices
-.IP "\fB-F\fP \fB\-\-pantech-mode NUM\fP         " 10
-Send a special control message used by Pantech devices.
-Value NUM will be used in control message as 'wValue'
+.IP "\fB-F\fP \fB\-\-pantech-mode\fP         " 10
+Send a special control message used by Pantech devices
 .IP "\fB-Z\fP \fB\-\-blackberry-mode\fP         " 10
 Send a special control message used by some newer Blackberry devices
 .IP "\fB-O\fP \fB\-\-sony-mode\fP         " 10
index 625b81d..8c147f2 100644 (file)
@@ -1,8 +1,8 @@
 /*
   Mode switching tool for controlling mode of 'multi-state' USB devices
-  Version 2.2.6, 2015/11/01
+  Version 2.2.0, 2014/05/29
 
-  Copyright (C) 2007 - 2015 Josua Dietze (mail to "digidietze" at the domain
+  Copyright (C) 2007 - 2014 Josua Dietze (mail to "digidietze" at the domain
   of the home page; or write a personal message through the forum to "Josh".
   NO SUPPORT VIA E-MAIL - please use the forum for that)
 
@@ -45,7 +45,7 @@
 
 /* Recommended tab size: 4 */
 
-#define VERSION "2.2.5"
+#define VERSION "2.2.0"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -112,14 +112,15 @@ static int usb_interrupt_io(libusb_device_handle *handle, int ep, char *bytes,
 char *TempPP=NULL;
 
 static struct libusb_context *ctx = NULL;
-static struct libusb_device *dev = NULL;
-static struct libusb_device_handle *devh = NULL;
+static struct libusb_device *dev;
+static struct libusb_device_handle *devh;
 static struct libusb_config_descriptor *active_config = NULL;
 
 int DefaultVendor=0, DefaultProduct=0, TargetVendor=0, TargetProduct=-1, TargetClass=0;
 int MessageEndpoint=0, ResponseEndpoint=0, ReleaseDelay=0;
 int targetDeviceCount=0, searchMode;
 int devnum=-1, busnum=-1;
+int ret;
 
 unsigned int ModeMap = 0;
 #define DETACHONLY_MODE                0x00000001
@@ -137,7 +138,6 @@ unsigned int ModeMap = 0;
 #define PANTECH_MODE           0x00001000
 #define HUAWEINEW_MODE         0x00002000
 
-int PantechMode=0;
 char verbose=0, show_progress=1, ResetUSB=0, CheckSuccess=0, config_read=0;
 char NeedResponse=0, NoDriverLoading=0, InquireDevice=0, sysmode=0, mbim=0;
 char StandardEject=0;
@@ -187,7 +187,7 @@ static struct option long_options[] = {
        {"mobileaction-mode",   no_argument, 0, 'A'},
        {"cisco-mode",          no_argument, 0, 'L'},
        {"blackberry-mode",             no_argument, 0, 'Z'},
-       {"pantech-mode",                required_argument, 0, 'F'},
+       {"pantech-mode",                no_argument, 0, 'F'},
        {"std-eject",                   no_argument, 0, 'K'},
        {"need-response",               no_argument, 0, 'n'},
        {"reset-usb",                   no_argument, 0, 'R'},
@@ -228,9 +228,7 @@ void readConfigFile(const char *configFilename)
        ParseParamBoolMap(configFilename, QisdaMode, ModeMap, QISDA_MODE);
        ParseParamBoolMap(configFilename, QuantaMode, ModeMap, QUANTA_MODE);
        ParseParamBoolMap(configFilename, BlackberryMode, ModeMap, BLACKBERRY_MODE);
-       ParseParamInt(configFilename, PantechMode);
-       if (PantechMode)
-               ModeMap |= PANTECH_MODE;
+       ParseParamBoolMap(configFilename, PantechMode, ModeMap, PANTECH_MODE);
        ParseParamBool(configFilename, StandardEject);
        ParseParamBool(configFilename, NoDriverLoading);
        ParseParamHex(configFilename, MessageEndpoint);
@@ -340,7 +338,7 @@ int readArguments(int argc, char **argv)
 
        while (1)
        {
-               c = getopt_long (argc, argv, "hejWQDndKHJSOBEGTNALZF:RItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:",
+               c = getopt_long (argc, argv, "hejWQDndKHJSOBEGTNALZFRItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:",
                                        long_options, &option_index);
 
                /* Detect the end of the options. */
@@ -376,8 +374,7 @@ int readArguments(int argc, char **argv)
                        case 'A': ModeMap = ModeMap + MOBILEACTION_MODE; break;
                        case 'L': ModeMap = ModeMap + CISCO_MODE; break;
                        case 'Z': ModeMap = ModeMap + BLACKBERRY_MODE; break;
-                       case 'F': ModeMap = ModeMap + PANTECH_MODE;
-                                               PantechMode = strtol(optarg, NULL, 10); break;
+                       case 'F': ModeMap = ModeMap + PANTECH_MODE; break;
                        case 'c': readConfigFile(optarg); break;
                        case 't': readConfigFile("stdin"); break;
                        case 'W': verbose = 1; show_progress = 1; count--; break;
@@ -425,10 +422,9 @@ int readArguments(int argc, char **argv)
 
 int main(int argc, char **argv)
 {
-       int ret=0, numDefaults=0, sonySuccess=0;
+       int numDefaults=0, sonySuccess=0;
        int currentConfig=0, defaultClass=0, interfaceClass=0;
        struct libusb_device_descriptor descriptor;
-       enum libusb_error libusbError;
 
        /* Make sure we have empty strings even if not set by config */
        TargetProductList[0] = '\0';
@@ -496,10 +492,7 @@ int main(int argc, char **argv)
        }
 
        /* libusb initialization */
-       if ((libusbError = libusb_init(&ctx)) != LIBUSB_SUCCESS) {
-               fprintf(stderr, "Error: Failed to initialize libusb. %s (%d)\n\n", libusb_error_name(libusbError), libusbError);
-               exit(1);
-       }
+       libusb_init(&ctx);
 
        if (verbose)
                libusb_set_debug(ctx, 3);
@@ -528,12 +521,10 @@ int main(int argc, char **argv)
                SHOW_PROGRESS(output," Found devices in default mode (%d)\n", numDefaults);
        } else {
                SHOW_PROGRESS(output," No devices in default mode found. Nothing to do. Bye!\n\n");
-               close_all();
                exit(0);
        }
        if (dev == NULL) {
                SHOW_PROGRESS(output," No bus/device match. Is device connected? Abort\n\n");
-               close_all();
                exit(0);
        } else {
                if (devnum == -1) {
@@ -544,13 +535,12 @@ int main(int argc, char **argv)
                libusb_open(dev, &devh);
                if (devh == NULL) {
                        SHOW_PROGRESS(output,"Error opening the device. Abort\n\n");
-                       abortExit();
+                       exit(1);
                }
        }
-
+       libusb_get_active_config_descriptor(dev, &active_config);
 
        /* Get current configuration of default device if parameter is set */
-       libusb_get_active_config_descriptor(dev, &active_config);
        if (Configuration > -1) {
                currentConfig = active_config->bConfigurationValue;
                SHOW_PROGRESS(output,"Current configuration number is %d\n", currentConfig);
@@ -560,7 +550,18 @@ int main(int argc, char **argv)
        libusb_get_device_descriptor(dev, &descriptor);
        defaultClass = descriptor.bDeviceClass;
        if (Interface == -1)
+#if defined TIZEN_MOD
+       {
+               if (!(active_config && active_config->interface && active_config->interface[0].altsetting)) {
+                       SHOW_PROGRESS(output,"Error: Could not get interface number. Abort\n\n");
+                       fprintf(stderr, "Error: Could not get interface number. Abort\n\n");
+                       exit(1);
+               }
+#endif
                Interface = active_config->interface[0].altsetting[0].bInterfaceNumber;
+#if defined TIZEN_MOD
+       }
+#endif
        SHOW_PROGRESS(output,"Use interface number %d\n", Interface);
 
        /* Get class of default device/interface */
@@ -572,28 +573,30 @@ int main(int argc, char **argv)
                        MessageEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_OUT);
                if (!ResponseEndpoint)
                        ResponseEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_IN);
+               libusb_free_config_descriptor(active_config);
                if (!MessageEndpoint) {
                        fprintf(stderr,"Error: message endpoint not given or found. Abort\n\n");
-                       abortExit();
+                       exit(1);
                }
                if (!ResponseEndpoint) {
                        fprintf(stderr,"Error: response endpoint not given or found. Abort\n\n");
-                       abortExit();
+                       exit(1);
                }
                SHOW_PROGRESS(output,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint, ResponseEndpoint);
-       }
+       } else
+               libusb_free_config_descriptor(active_config);
 
        if (interfaceClass == -1) {
                fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface);
-               abortExit();
+               exit(1);
        }
 
        if (defaultClass == 0)
                defaultClass = interfaceClass;
        else
-               if (interfaceClass == 8 && defaultClass != 8 && defaultClass != 0xef && defaultClass != 0xff) {
-                       /* Unexpected default class combined with differing interface class */
-                       SHOW_PROGRESS(output,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass);
+               if (interfaceClass == 8 && defaultClass != 8) {
+                       /* Weird device with default class other than 0 and differing interface class */
+                       SHOW_PROGRESS(output,"Ambiguous Class/InterfaceClass: 0x%02x/0x08\n", defaultClass);
                        defaultClass = 8;
                }
 
@@ -601,7 +604,7 @@ int main(int argc, char **argv)
                if (defaultClass != 8) {
                        fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d;\n"
                                "       interface class is %d, expected 8. Abort\n\n", Interface, defaultClass);
-                       abortExit();
+                       exit(1);
                }
 
        if (InquireDevice && show_progress) {
@@ -629,7 +632,7 @@ int main(int argc, char **argv)
         */
        if ( ModeMap & (ModeMap-1) ) {
                fprintf(output,"Multiple special modes selected; check configuration. Abort\n\n");
-               abortExit();
+               exit(1);
        }
 
        if ((strlen(MessageContent) || StandardEject) && ModeMap ) {
@@ -701,10 +704,7 @@ int main(int argc, char **argv)
        }
        if(ModeMap & PANTECH_MODE) {
                detachDriver();
-               if (PantechMode > 1)
-                       switchPantechMode();
-               else
-                       SHOW_PROGRESS(output,"Waiting for auto-switch of Pantech modem ...\n");
+               switchPantechMode();
        }
        if(ModeMap & SONY_MODE) {
                if (CheckSuccess)
@@ -721,8 +721,8 @@ int main(int argc, char **argv)
                else
                        MessageContent3[0] = '\0';
 
-               strcpy(MessageContent,"5553424387654321000000000000061e000000000000000000000000000000");
-               strcpy(MessageContent2,"5553424397654321000000000000061b000000020000000000000000000000");
+               strcpy(MessageContent,"5553424312345678000000000000061e000000000000000000000000000000");
+               strcpy(MessageContent2,"5553424312345679000000000000061b000000020000000000000000000000");
                NeedResponse = 1;
                switchSendMessage();
        } else if (ModeMap & HUAWEINEW_MODE) {
@@ -759,21 +759,20 @@ int main(int argc, char **argv)
        /* No "removal" check if these are set */
        if ((Configuration > 0 || AltSetting > -1) && !ResetUSB) {
                libusb_close(devh);
-               devh = NULL;
+               devh = 0;
        }
 
        if (ResetUSB) {
                resetUSB();
-               devh = NULL;
-       }
-
-       if (searchMode == SEARCH_BUSDEV && sysmode) {
-               printf("ok:busdev\n");
-               close_all();
-               exit(0);
+               devh = 0;
        }
 
        if (CheckSuccess) {
+               if (searchMode == SEARCH_BUSDEV && sysmode) {
+                       SHOW_PROGRESS(output,"Bus/dev search active, refer success check to wrapper. Bye!\n\n");
+                       printf("ok:busdev\n");
+                       goto CLOSING;
+               }
                if (checkSuccess()) {
                        if (sysmode) {
                                if (NoDriverLoading)
@@ -803,7 +802,11 @@ int main(int argc, char **argv)
                else
                        SHOW_PROGRESS(output,"-> Run lsusb to note any changes. Bye!\n\n");
        }
-       close_all();
+CLOSING:
+       if (sysmode)
+               closelog();
+       if (devh)
+               libusb_close(devh);
        exit(0);
 }
 
@@ -811,7 +814,6 @@ int main(int argc, char **argv)
 /* Get descriptor strings if available (identification details) */
 void deviceDescription ()
 {
-       int ret=0;
        char* c;
        memset (imanufact, ' ', DESCR_MAX);
        memset (iproduct, ' ', DESCR_MAX);
@@ -867,7 +869,7 @@ int deviceInquire ()
        };
        char *command;
        char data[36];
-       int i, ret=0;
+       int i;
 
        command = malloc(31);
        if (command == NULL) {
@@ -1081,14 +1083,14 @@ int switchSendMessage ()
 skip:
        SHOW_PROGRESS(output," Device is gone, skip any further commands\n");
        libusb_close(devh);
-       devh = NULL;
+       devh = 0;
        return 2;
 }
 
 
 int switchConfiguration ()
 {
-       int ret, count = SWITCH_CONFIG_MAXTRIES;
+       int count = SWITCH_CONFIG_MAXTRIES; 
 
        SHOW_PROGRESS(output,"Change configuration to %i ...\n", Configuration);
        while (((ret = libusb_set_configuration(devh, Configuration)) < 0) && --count) {
@@ -1106,13 +1108,9 @@ int switchConfiguration ()
 
 int switchAltSetting ()
 {
-       int ret;
+
        SHOW_PROGRESS(output,"Change to alt setting %i ...\n", AltSetting);
        ret = libusb_claim_interface(devh, Interface);
-       if (ret < 0) {
-               SHOW_PROGRESS(output," Could not claim interface (error %d). Skip AltSetting\n", ret);
-               return 0;
-       }
        ret = libusb_set_interface_alt_setting(devh, Interface, AltSetting);
        libusb_release_interface(devh, Interface);
        if (ret < 0) {
@@ -1125,20 +1123,19 @@ int switchAltSetting ()
 
 void switchHuaweiMode ()
 {
-       int ret;
+
        SHOW_PROGRESS(output,"Send old Huawei control message ...\n");
        ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, \
                LIBUSB_REQUEST_SET_FEATURE, 00000001, 0, (unsigned char *)buffer, 0, 1000);
        if (ret != 0) {
                fprintf(stderr, "Error: Huawei control message failed (error %d). Abort\n\n", ret);
-               exit(0);
+               exit(1);
        }
 }
 
 
 void switchSierraMode ()
 {
-       int ret;
        SHOW_PROGRESS(output,"Send Sierra control message\n");
        ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR, 0x0b, 00000001, 0, (unsigned char *)buffer, 0, 1000);
        if (ret == LIBUSB_ERROR_PIPE) {
@@ -1147,14 +1144,13 @@ void switchSierraMode ()
        }
        if (ret < 0) {
                fprintf(stderr, "Error: Sierra control message failed (error %d). Abort\n\n", ret);
-           exit(0);
+           exit(1);
        }
 }
 
 
 void switchGCTMode ()
 {
-       int ret;
        ret = libusb_claim_interface(devh, Interface);
        if (ret != 0) {
                SHOW_PROGRESS(output," Could not claim interface (error %d). Skip GCT sequence\n", ret);
@@ -1172,49 +1168,45 @@ void switchGCTMode ()
        }
        libusb_release_interface(devh, Interface);
        if (ret < 0)
-               exit(0);
+               exit(1);
 }
 
 
 void switchKobilMode() {
-       int ret;
        SHOW_PROGRESS(output,"Send Kobil control message ...\n");
        ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
                        0x88, 0, 0, (unsigned char *)buffer, 8, 1000);
        if (ret < 0) {
                fprintf(stderr, "Error: Kobil control message failed (error %d). Abort\n\n", ret);
-               exit(0);
+               exit(1);
        }
 }
 
 
 void switchQisdaMode () {
-       int ret;
        SHOW_PROGRESS(output,"Sending Qisda control message ...\n");
        memcpy(buffer, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16);
        ret = libusb_control_transfer(devh, 0x40, 0x04, 0, 0, (unsigned char *)buffer, 16, 1000);
        if (ret < 0) {
                fprintf(stderr, "Error: Qisda control message failed (error %d). Abort\n\n", ret);
-               exit(0);
+               exit(1);
        }
 }
 
 
 void switchQuantaMode() {
-       int ret;
        SHOW_PROGRESS(output,"Send Quanta control message ...\n");
        ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
                        0xff, 0, 0, (unsigned char *)buffer, 0, 1000);
        if (ret < 0) {
                SHOW_PROGRESS(output,"Error: Quanta control message failed (error %d). Abort\n\n", ret);
-               exit(0);
+               exit(1);
        }
 }
 
 
 void switchBlackberryMode ()
 {
-       int ret;
        SHOW_PROGRESS(output,"Send Blackberry control message 1 ...\n");
        ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
                        0xb1, 0x0000, 0, (unsigned char *)buffer, 8, 1000);
@@ -1226,19 +1218,18 @@ void switchBlackberryMode ()
                        0xa9, 0x000e, 0, (unsigned char *)buffer, 2, 1000);
        if (ret != 2) {
                fprintf(stderr, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret);
-               exit(0);
+               exit(1);
        }
 }
 
 
 void switchPantechMode()
 {
-       int ret;
-       SHOW_PROGRESS(output,"Send Pantech control message, wValue %d ...\n", PantechMode);
-       ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x70, PantechMode, 0, (unsigned char *)buffer, 0, 1000);
+       SHOW_PROGRESS(output,"Send Pantech control message ...\n");
+       ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x70, 2, 0, (unsigned char *)buffer, 0, 1000);
        if (ret < 0) {
                SHOW_PROGRESS(output," Error: Pantech control message failed (error %d). Abort\n\n", ret);
-               exit(0);
+               exit(1);
        }
 }
 
@@ -1257,7 +1248,7 @@ void switchPantechMode()
 
 void switchActionMode ()
 {
-       int ret, i;
+       int i;
        SHOW_PROGRESS(output,"Send MobileAction control sequence ...\n");
        memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE);
        libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS + LIBUSB_RECIPIENT_INTERFACE, 0x09, 0x0300, 0, (unsigned char *)buffer, SIZE, 1000);
@@ -1310,17 +1301,16 @@ void switchActionMode ()
 
 void switchSequansMode() {
 
-       int ret;
        SHOW_PROGRESS(output,"Send Sequans control message\n");
        ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, SQN_SET_DEVICE_MODE_REQUEST, SQN_CUSTOM_DEVICE_MODE, 0, (unsigned char *)buffer, 0, 1000);
        if (ret < 0) {
                fprintf(stderr, "Error: Sequans request failed (error %d). Abort\n\n", ret);
-           exit(0);
+           exit(1);
        }
 }
 
 void switchCiscoMode() {
-       int ret, i;
+       int i;
        char* msg[11];
 
        msg[0] = "55534243f83bcd810002000080000afd000000030000000100000000000000";
@@ -1339,15 +1329,12 @@ void switchCiscoMode() {
        ret = libusb_claim_interface(devh, Interface);
        if (ret < 0) {
                SHOW_PROGRESS(output," Could not claim interface (error %d). Abort\n", ret);
-               abortExit();
+               exit(1);
        }
 //     libusb_clear_halt(devh, MessageEndpoint);
        if (show_progress)
                fflush(output);
 
-//     ret = read_bulk(ResponseEndpoint, ByteString, 13);
-//     SHOW_PROGRESS(output," Extra response (CSW) read, result %d\n",ret);
-
        for (i=0; i<11; i++) {
                if ( sendMessage(msg[i], i+1) )
                        goto skip;
@@ -1356,14 +1343,6 @@ void switchCiscoMode() {
                ret = read_bulk(ResponseEndpoint, ByteString, 13);
                if (ret < 0)
                        goto skip;
-               if (ret < 13) {
-                       SHOW_PROGRESS(output," Repeat reading the response to bulk message %d ...\n",i+1);
-                       ret = read_bulk(ResponseEndpoint, ByteString, 13);
-               }
-               if (ret < 13) {
-                       SHOW_PROGRESS(output," Repeat reading the response to bulk message %d ...\n",i+1);
-                       ret = read_bulk(ResponseEndpoint, ByteString, 13);
-               }
        }
 
        if (ReleaseDelay) {
@@ -1378,13 +1357,13 @@ void switchCiscoMode() {
 skip:
        SHOW_PROGRESS(output,"Device returned error %d, skip further commands\n", ret);
        libusb_close(devh);
-       devh = NULL;
+       devh = 0;
 }
 
 
 int switchSonyMode ()
 {
-       int ret, i, found;
+       int i, found;
        detachDriver();
 
        if (CheckSuccess) {
@@ -1395,12 +1374,12 @@ int switchSonyMode ()
        ret = libusb_control_transfer(devh, 0xc0, 0x11, 2, 0, (unsigned char *)buffer, 3, 100);
        if (ret < 0) {
                fprintf(stderr, "Error: Sony control message failed (error %d). Abort\n\n", ret);
-               exit(0);
+               exit(1);
        } else
                SHOW_PROGRESS(output," OK, control message sent, wait for device to return ...\n");
 
        libusb_close(devh);
-       devh = NULL;
+       devh = 0;
 
        /* Now waiting for the device to reappear */
        devnum=-1;
@@ -1450,7 +1429,6 @@ int switchSonyMode ()
 int detachDriver()
 {
 
-       int ret;
        // Driver already detached during SCSI inquiry ?
        if (InquireDevice == 2)
                return 1;
@@ -1484,7 +1462,7 @@ int detachDriver()
 
 int sendMessage(char* message, int count)
 {
-       int ret, message_length;
+       int message_length;
 
        if (strlen(message) % 2 != 0) {
                fprintf(stderr, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count);
@@ -1507,7 +1485,7 @@ int sendMessage(char* message, int count)
 
 int checkSuccess()
 {
-       int ret, i;
+       int i=0;
        int newTargetCount, success=0;
 
        SHOW_PROGRESS(output,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess);
@@ -1519,7 +1497,7 @@ int checkSuccess()
         */
        if ((TargetVendor || TargetClass) && devh) {
                libusb_close(devh);
-               devh = NULL;
+               devh = 0;
        }
 
        /* if target ID is not given but target class is, assign default as target;
@@ -1545,7 +1523,7 @@ int checkSuccess()
                        if (ret < 0) {
                                SHOW_PROGRESS(output," Original device can't be accessed anymore. Good.\n");
                                libusb_close(devh);
-                               devh = NULL;
+                               devh = 0;
                                break;
                        }
                        if (i == CheckSuccess-1) {
@@ -1568,7 +1546,7 @@ int checkSuccess()
                                libusb_open(dev, &devh);
                                deviceDescription();
                                libusb_close(devh);
-                               devh = NULL;
+                               devh = 0;
                                if (verbose) {
                                        fprintf(output,"\nFound target device %03d on bus %03d\n", \
                                        libusb_get_device_address(dev), libusb_get_bus_number(dev));
@@ -1624,7 +1602,7 @@ int checkSuccess()
 
 int write_bulk(int endpoint, char *message, int length)
 {
-       int ret = usb_bulk_io(devh, endpoint, message, length, 3000);
+       ret = usb_bulk_io(devh, endpoint, message, length, 3000);
        if (ret >= 0 ) {
                SHOW_PROGRESS(output," OK, message successfully sent\n");
        } else
@@ -1638,7 +1616,7 @@ int write_bulk(int endpoint, char *message, int length)
 
 int read_bulk(int endpoint, char *buffer, int length)
 {
-       int ret = usb_bulk_io(devh, endpoint, buffer, length, 3000);
+       ret = usb_bulk_io(devh, endpoint, buffer, length, 3000);
        if (ret >= 0 ) {
                SHOW_PROGRESS(output," Response successfully read (%d bytes).\n", ret);
        } else
@@ -1652,9 +1630,12 @@ int read_bulk(int endpoint, char *buffer, int length)
 
 void release_usb_device(int __attribute__((unused)) dummy) {
        SHOW_PROGRESS(output,"Program cancelled by system. Bye!\n\n");
-       if (devh)
+       if (devh) {
                libusb_release_interface(devh, Interface);
-       close_all();
+               libusb_close(devh);
+       }
+       if (sysmode)
+               closelog();
        exit(0);
 
 }
@@ -1824,17 +1805,17 @@ int find_first_bulk_endpoint(int direction)
 
 int get_current_configuration()
 {
+       int cfg;
        SHOW_PROGRESS(output,"Get the current device configuration ...\n");
-       if (active_config != NULL) {
-               libusb_free_config_descriptor(active_config);
-               active_config = NULL;
-       }
-       int ret = libusb_get_active_config_descriptor(dev, &active_config);
-       if (ret < 0) {
-               SHOW_PROGRESS(output," Determining the active configuration failed (error %d). Abort\n", ret);
-               abortExit();
-       }
-       return active_config->bConfigurationValue;
+       if (active_config == NULL)
+               libusb_get_active_config_descriptor(dev, &active_config);
+
+       cfg = active_config->bConfigurationValue;
+       libusb_free_config_descriptor(active_config);
+       if (ret < 0)
+               exit(1);
+       else
+               return cfg;
 }
 
 int get_interface_class()
@@ -1878,7 +1859,7 @@ char* ReadParseParam(const char* FileName, char *VariableName)
                        }
                        if (file==NULL) {
                                fprintf(stderr, "Error: Could not find file %s. Abort\n\n", FileName);
-                               abortExit();
+                               exit(1);
                        } else {
                                token = fgets(Str, LINE_DIM-1, file);
                        }
@@ -2000,32 +1981,11 @@ int hexstr2bin(const char *hex, char *buffer, int len)
        return 0;
 }
 
-void close_all()
-{
-       if (active_config)
-               libusb_free_config_descriptor(active_config);
-       if (devh)
-               libusb_close(devh);
-       // libusb_exit will crash on Raspbian 7, crude protection
-#ifndef __ARMEL__
-       libusb_exit(NULL);
-#endif
-       if (sysmode)
-               closelog();
-}
-
-void abortExit()
-{
-       close_all();
-       exit(1);
-}
-
-
 void printVersion()
 {
        char* version = VERSION;
        fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
-               " * Version %s (C) Josua Dietze 2015\n"
+               " * Version %s (C) Josua Dietze 2014\n"
                " * Based on libusb1/libusbx\n\n"
                " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version);
 }
@@ -2061,7 +2021,6 @@ void printHelp()
        " -L, --cisco-mode              apply a special procedure\n"
        " -B, --qisda-mode              apply a special procedure\n"
        " -E, --quanta-mode             apply a special procedure\n"
-       " -F, --pantech-mode NUM        apply a special procedure, pass NUM through\n"
        " -R, --reset-usb               reset the device after all other actions\n"
        " -Q, --quiet                   don't show progress or error messages\n"
        " -W, --verbose                 print all settings and debug output\n"
index 7a94994..b28b345 100644 (file)
 
 DisableSwitching=0
 
-# Disable check for MBIM module presence and configuration globally (to aid
-# special embedded environments)
-
-DisableMBIMGlobal=0
 
 # Enable logging (results in a extensive report file in /var/log, named
 # "usb_modeswitch_<interface-name>" and probably others
@@ -28,4 +24,4 @@ EnableLogging=1
 # larly with USB 3.0 ports. Set this to at least 3 (seconds) in that case.
 # Does nothing if the current system value is same or higher
 
-#SetStorageDelay=4
+SetStorageDelay=5
index c4831ce..69532c2 100644 (file)
@@ -2,8 +2,8 @@
   This file is part of usb_modeswitch, a mode switching tool for controlling
   the mode of 'multi-state' USB devices
 
-  Version 2.2.6, 2015/11/01
-  Copyright (C) 2007 - 2015  Josua Dietze
+  Version 2.2.0, 2014/05/29
+  Copyright (C) 2007 - 2014  Josua Dietze
 
   Config file parsing stuff borrowed from Guillaume Dargaud
   (http://www.gdargaud.net/Hack/SourceCode.html)
@@ -60,8 +60,6 @@ int hex2byte(const char *hex);
 int hexstr2bin(const char *hex, char *buffer, int len);
 void printVersion();
 void printHelp();
-void close_all();
-void abortExit();
 int readArguments(int argc, char **argv);
 void deviceDescription();
 int deviceInquire();
index 00765ad..4e172e2 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# part of usb_modeswitch 2.2.6
+# part of usb_modeswitch 2.2.0
 device_in()
 {
        if [ ! -e /var/lib/usb_modeswitch/$1 ]; then
@@ -73,23 +73,20 @@ case "$1" in
                exit 0
                ;;
 esac
+exec 1<&- 2<&- 5<&- 7<&-
 (
-IFS='/' read -r p1 p2 <<EOF
-$1
-EOF
-PATH=/bin:/sbin:/usr/bin:/usr/sbin
 count=20
 while [ $count != 0 ]; do
        if [ ! -e "/usr/sbin/usb_modeswitch_dispatcher" ]; then
                sleep 1
                count=$(($count - 1))
        else
-               if [ -e "/etc/systemd/system/usb_modeswitch@.service" ]; then
-                       exec systemctl --no-block start usb_modeswitch@$p1'_'$p2.service
-               elif [ -e "/etc/init/usb-modeswitch-upstart.conf" ]; then
-                       exec initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1
+               if [ -e "/etc/init/usb-modeswitch-upstart.conf" ]; then
+                       exec /sbin/initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1
+               elif [ -e "/etc/systemd/system/usb_modeswitch@.service" ]; then
+                       exec /usr/bin/systemctl --no-block start usb_modeswitch@$1.service
                else
-                       exec usb_modeswitch_dispatcher --switch-mode $1 &
+                       exec /usr/sbin/usb_modeswitch_dispatcher --switch-mode $1 &
                fi
                exit 0
        fi
index 658e164..5e99e72 100755 (executable)
@@ -9,8 +9,8 @@
 # the mode switching program with the matching parameter
 # file from /usr/share/usb_modeswitch
 #
-# Part of usb-modeswitch-2.2.6 package
-# (C) Josua Dietze 2009-2015
+# Part of usb-modeswitch-2.2.0 package
+# (C) Josua Dietze 2009-2014
 
 set arg0 [lindex $argv 0]
 if [regexp {\.tcl$} $arg0] {
@@ -24,10 +24,9 @@ if [regexp {\.tcl$} $arg0] {
 # Setting of these switches is done in the global config
 # file (/etc/usb_modeswitch.conf) if available
 
-set flags(logging) 1
+set flags(logging) 0
 set flags(noswitching) 0
 set flags(stordelay) 0
-set flags(logwrite) 0
 
 # Execution starts at file bottom
 
@@ -36,6 +35,7 @@ proc {Main} {argv argc} {
 global scsi usb config match device flags setup devdir loginit
 
 set flags(config) ""
+set flags(logwrite) 0
 Log "[ParseGlobalConfig]"
 
 # The facility to add a symbolic link pointing to the
@@ -46,7 +46,7 @@ Log "[ParseGlobalConfig]"
 # to udev for symlink creation
 
 # This is run once for every port of LISTED devices by
-# a udev rule
+# an udev rule
 
 if {[lindex $argv 0] == "--symlink-name"} {
        puts -nonewline [SymLinkName [lindex $argv 1]]
@@ -54,18 +54,20 @@ if {[lindex $argv 0] == "--symlink-name"} {
 }
 
 if {[lindex $argv 0] == "--switch-systemd"} {
-       set argList [split [lindex $argv 1] _]
+       set device [string trim [lindex $argv 1] "/-"]
+       set device [regsub {/} $device "-"]
+       set argList [list "" $device]
        Log "\nStarted via systemd"
 } else {
        if {[lindex $argv 0] == "--switch-upstart"} {
                Log "\nStarted via upstart"
        }
        set argList [split [lindex $argv 1] /]
-}
-if [string length [lindex $argList 1]] {
-       set device [lindex $argList 1]
-} else {
-       set device "noname"
+       if [string length [lindex $argList 1]] {
+               set device [lindex $argList 1]
+       } else {
+               set device "noname"
+       }
 }
 if {$flags(stordelay) > 0} {
        SetStorageDelay $flags(stordelay)
@@ -109,7 +111,10 @@ if {[string length [lindex $argList 0]] == 0} {
                SafeExit
        } else {
                if {![regexp {(.*?):} [lindex $argList 1] d dev_top]} {
-                       if {![regexp {([0-9]+-[0-9]+\.?[0-9]*.*)} [lindex $argList 1] d dev_top]} {
+                       if [regexp {([0-9]+-[0-9]+\.?[0-9]*.*)} [lindex $argList 1] d dev_top] {
+                               # new udev rules file, got to check class of first interface
+                               set ifChk 1
+                       } else {
                                Log "Could not determine device dir from udev values! Exit"
                                SafeExit
                        }
@@ -128,14 +133,20 @@ if {![file isdirectory $devdir]} {
 Log "Use top device dir $devdir"
 
 set iface 0
-Log "Check class of first interface ..."
-set config(class) [IfClass 0]
-if {$config(class) < 0} {
-       Log " No access to interface 0. Exit"
-       SafeExit
+if $ifChk {
+       Log "Check class of first interface ..."
+       set config(class) [IfClass 0]
+       if {$iface < 0} {
+               Log " No access to interface 0. Exit"
+               SafeExit
+       }
+       Log " Interface class is $config(class)."
+       if {$config(class) == "08" || $config(class) == "03"} {
+       } else {
+               Log "No install mode found. Aborting"
+               exit
+       }
 }
-Log " Interface 0 class is $config(class)."
-
 set ifdir [file tail [IfDir $iface]]
 regexp {:([0-9]+\.[0-9]+)$} $ifdir d iface
 
@@ -249,21 +260,18 @@ foreach mconfig $configList {
                        set busParam ""
                        set devParam ""
                }
-               set flags(config) [ConfigGet conffile $mconfig]
-               ParseDeviceConfig $flags(config)
+               set configBuffer [ConfigGet conffile $mconfig]
+               ParseDeviceConfig $configBuffer
                if [regexp -nocase {/[0-9a-f]+:#} $flags(config)] {
                        Log "Note: Using generic manufacturer configuration for \"$flags(os)\""
                }
-               if $flags(nombim) {
-                       set config(NoMBIMCheck) 1
-               }
-               if {$config(WaitBefore) != ""} {
-                       Log "Delay time of $config(WaitBefore) seconds"
-                       append config(WaitBefore) "000"
-                       after $config(WaitBefore)
+               if {$config(waitBefore) != ""} {
+                       Log "Delay time of $config(waitBefore) seconds"
+                       append config(waitBefore) "000"
+                       after $config(waitBefore)
                        Log " wait is over, start mode switch"
                }
-               if {$config(NoMBIMCheck)==0 && $usb(bNumConfigurations) > 1} {
+               if {$config(noMBIMCheck)==0 && $usb(bNumConfigurations) > 1} {
                        Log "Device may have an MBIM configuration, check driver ..."
                        if [CheckMBIM] {
                                Log " driver for MBIM devices is available"
@@ -274,8 +282,8 @@ foreach mconfig $configList {
                                        set cfgno [string trim $cfgno]
                                        if {$cfgno > 0} {
                                                set config(Configuration) $cfgno
-                                               set config(DriverModule) ""
-                                               set flags(config) "Configuration=$cfgno"
+                                               set config(driverModule) ""
+                                               set configBuffer "Configuration=$cfgno"
                                        } else {
                                                Log " No MBIM configuration found, switch to legacy modem mode"
                                        }
@@ -284,16 +292,11 @@ foreach mconfig $configList {
                                Log " no MBIM driver found, switch to legacy modem mode"
                        }
                }
-               if [PantechAutoSwitch] {
-                       Log "Waiting for Pantech auto-modeswitch"
-                       set report "ok:busdev"
-                       break
-               }
-               UnbindDriver $devdir $ifdir
+
                # Now we are actually switching
                if $flags(logging) {
-                       Log "Command to be run:\nusb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$flags(config)"
-                       set report [exec /usr/sbin/usb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1]
+                       Log "Command to be run:\nusb_modeswitch -W -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$configBuffer"
+                       set report [exec /usr/sbin/usb_modeswitch -W -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$configBuffer" 2>@1]
                        Log "\nVerbose debug output of usb_modeswitch and libusb follows"
                        Log "(Note that some USB errors are to be expected in the process)"
                        Log "--------------------------------"
@@ -301,7 +304,7 @@ foreach mconfig $configList {
                        Log "--------------------------------"
                        Log "(end of usb_modeswitch output)\n"
                } else {
-                       set report [exec /usr/sbin/usb_modeswitch -Q -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1]
+                       set report [exec /usr/sbin/usb_modeswitch -Q -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$configBuffer" 2>@1]
                }
                break
        } else {
@@ -313,10 +316,6 @@ foreach mconfig $configList {
 # done by usb_modeswitch and logged via syslog OR bus/dev
 # parameter were used; then we do check for success HERE
 
-if {$config(Configuration) != ""} {
-       set ifdir [regsub {(\d):\d+\.0} $ifdir "\\1:$config(Configuration).0"]
-}
-
 if [regexp {ok:busdev} $report] {
        if [CheckSuccess $devdir] {
                Log "Mode switching was successful, found $usb(idVendor):$usb(idProduct) ($usb(manufacturer): $usb(product))"
@@ -343,13 +342,11 @@ if [regexp {ok:busdev} $report] {
        ReadUSBAttrs $devdir $ifdir
 }
 
-# Checking for bound drivers if there is an interface with class 0xff
+# Now checking for bound drivers (only for class 0xff)
 
-if {$config(DriverModule) != "" && [regexp {ok:} $report]} {
-       if [HasFF] {
-               AddToList link_list $usb(idVendor):$usb(idProduct)
-       } else {
-               set config(DriverModule) ""
+if {$config(driverModule) != "" && $usb($ifdir/bInterfaceClass) != "" && [regexp {ok:} $report]} {
+       if {$usb($ifdir/bInterfaceClass) != "ff"} {
+               set config(driverModule) ""
                Log " No vendor-specific class found, skip driver check"
        }
 }
@@ -357,7 +354,7 @@ if {$config(DriverModule) != "" && [regexp {ok:} $report]} {
 # If module is set (it is by default), driver shall be loaded.
 # If not, then NoDriverLoading is active
 
-if {$config(DriverModule) != ""} {
+if {$config(driverModule) != ""} {
        if {[string length "$usb(idVendor)$usb(idProduct)"] < 8} {
                if {![regexp {ok:(\w{4}):(\w{4})} $report d usb(idVendor) usb(idProduct)]} {
                        Log "No target vendor/product ID found or given, can't continue. Abort"
@@ -365,10 +362,11 @@ if {$config(DriverModule) != ""} {
                }
        }
        # wait for any drivers to bind automatically
-       after 1500
+       after 1000
        Log "Now check for bound driver ..."
        if {![file exists $devdir/$ifdir/driver]} {
                Log " no driver has bound to interface 0 yet"
+               AddToList link_list $usb(idVendor):$usb(idProduct)
 
                # If device is known, the sh wrapper will take care, else:
                if {[InBindList $usb(idVendor):$usb(idProduct)] == 0} {
@@ -562,13 +560,6 @@ set rc [open $configFile r]
 while {![eof $rc]} {
        gets $rc line
        if [regexp {^#} [string trim $line]] {continue}
-       if [regexp {DisableMBIMGlobal\s*=\s*([^\s]+)} $line d val] {
-               if [regexp -nocase {1|yes|true} $val] {
-                       set flags(nombim) 1
-               } else {
-                       set flags(nombim) 0
-               }
-       }
        if [regexp {DisableSwitching\s*=\s*([^\s]+)} $line d val] {
                if [regexp -nocase {1|yes|true} $val] {
                        set flags(noswitching) 1
@@ -577,8 +568,6 @@ while {![eof $rc]} {
        if [regexp {EnableLogging\s*=\s*([^\s]+)} $line d val] {
                if [regexp -nocase {1|yes|true} $val] {
                        set flags(logging) 1
-               } else {
-                       set flags(logging) 0
                }
        }
        if [regexp {SetStorageDelay\s*=\s*([^\s]+)} $line d val] {
@@ -594,28 +583,51 @@ return "Use global config file: $configFile"
 # end of proc {ParseGlobalConfig}
 
 
-proc ParseDeviceConfig {cfg} {
+proc ParseDeviceConfig {configContent} {
 
 global config
-set config(DriverModule) ""
-set config(DriverIDPath) ""
-set config(WaitBefore) ""
-set config(TargetVendor) ""
-set config(TargetProduct) ""
-set config(TargetClass) ""
+set config(driverModule) ""
+set config(driverIDPath) ""
+set config(waitBefore) ""
+set config(targetVendor) ""
+set config(targetProduct) ""
+set config(targetClass) ""
 set config(Configuration) ""
-set config(NoMBIMCheck) 0
-set config(PantechMode) 0
-set config(CheckSuccess) 20
+set config(noMBIMCheck) 0
+set config(checkSuccess) 20
 set loadDriver 1
 
-foreach pname [lsort [array names config]] {
-       if [regexp -line "^\[^# \]*?$pname.*?= *(0x(\\w+)|\"(\[0-9a-fA-F,\]+)\"|(\[0-9\]+)) *\$" $cfg d config($pname)] {
-#              Log "config: $pname set to $config($pname)"
-       }
+if [regexp -line {^[^#]*?TargetVendor.*?=.*?0x(\w+).*?$} $configContent d config(targetVendor)] {
+       Log "config: TargetVendor set to $config(targetVendor)"
 }
-
-if [regexp -line {^[^#]*?NoDriverLoading.*?=.*?(1|yes|true).*?$} $cfg] {
+if [regexp -line {^[^#]*?TargetProduct.*?=.*?0x(\w+).*?$} $configContent d config(targetProduct)] {
+       Log "config: TargetProduct set to $config(targetProduct)"
+}
+if [regexp -line {^[^#]*?TargetProductList.*?=.*?"([0-9a-fA-F,]+).*?$} $configContent d config(targetProduct)] {
+       Log "config: TargetProductList set to $config(targetProduct)"
+}
+if [regexp -line {^[^#]*?TargetClass.*?=.*?0x(\w+).*?$} $configContent d config(targetClass)] {
+       Log "config: TargetClass set to $config(targetClass)"
+}
+if [regexp -line {^[^#]*?Configuration.*?=.*?([0-9]+).*?$} $configContent d config(Configuration)] {
+       Log "config: Configuration (target) set to $config(Configuration)"
+}
+if [regexp -line {^[^#]*?DriverModule.*?=.*?(\w+).*?$} $configContent d config(driverModule)] {
+       Log "config: DriverModule set to $config(driverModule)"
+}
+if [regexp -line {^[^#]*?DriverIDPath.*?=.*?"?([/\-\w]+).*?$} $configContent d config(driverIDPath)] {
+       Log "config: DriverIDPath set to $config(driverIDPath)"
+}
+if [regexp -line {^[^#]*?CheckSuccess.*?=.*?([0-9]+).*?$} $configContent d config(checkSuccess)] {
+       Log "config: CheckSuccess set to $config(checkSuccess)"
+}
+if [regexp -line {^[^#]*?WaitBefore.*?=.*?([0-9]+).*?$} $configContent d config(waitBefore)] {
+       Log "config: WaitBefore set to $config(waitBefore)"
+}
+if [regexp -line {^[^#]*?NoMBIMCheck.*?=.*?([0-9]+).*?$} $configContent d config(noMBIMCheck)] {
+       Log "config: noMBIMCheck set to $config(noMBIMCheck)"
+}
+if [regexp -line {^[^#]*?NoDriverLoading.*?=.*?(1|yes|true).*?$} $configContent] {
        set loadDriver 0
        Log "config: NoDriverLoading is set to active"
 }
@@ -623,19 +635,19 @@ if [regexp -line {^[^#]*?NoDriverLoading.*?=.*?(1|yes|true).*?$} $cfg] {
 # For general driver loading; TODO: add respective device names.
 # Presently only useful for HSO devices (which are recounted now)
 if $loadDriver {
-       if {$config(DriverModule) == ""} {
-               set config(DriverModule) "option"
-               set config(DriverIDPath) "/sys/bus/usb-serial/drivers/option1"
+       if {$config(driverModule) == ""} {
+               set config(driverModule) "option"
+               set config(driverIDPath) "/sys/bus/usb-serial/drivers/option1"
        } else {
-               if {$config(DriverIDPath) == ""} {
-                       set config(DriverIDPath) "/sys/bus/usb/drivers/$config(DriverModule)"
+               if {$config(driverIDPath) == ""} {
+                       set config(driverIDPath) "/sys/bus/usb/drivers/$config(driverModule)"
                }
        }
-       Log "Driver module is \"$config(DriverModule)\", ID path is $config(DriverIDPath)\n"
+       Log "Driver module is \"$config(driverModule)\", ID path is $config(driverIDPath)\n"
 } else {
        Log "Driver will not be handled by usb_modeswitch"
 }
-set config(WaitBefore) [string trimleft $config(WaitBefore) 0]
+set config(waitBefore) [string trimleft $config(waitBefore) 0]
 
 }
 # end of proc {ParseDeviceConfig}
@@ -724,7 +736,7 @@ exit
 
 
 proc {SymLinkName} {path} {
-global device flags
+global device
 
 proc {hasInterrupt} {ifDir} {
        if {[llength [glob -nocomplain $ifDir/ttyUSB*]] == 0} {
@@ -762,17 +774,16 @@ if [file exists $linkpath] {
                }
        }
 }
-if {![regexp {([0-9]+-[0-9]+[\.0-9]*:[^/]*).*(ttyUSB[0-9]+)} $path d myDev myPort]} {
+
+if {![regexp {ttyUSB[0-9]+} $path myPort]} {
        if $flags(logging) {
                set device [clock clicks]
-               set flags(logwrite) 1
                Log "$loginit\nThis is not a ttyUSB port. Abort"
        }
        return ""
 }
 
-set device ttyUSB_$myDev
-set flags(logwrite) 1
+set device $myPort
 Log "$loginit\nMy name is $myPort\n"
 
 if {![regexp {(.*?[0-9]+)\.([0-9]+)/ttyUSB} /sys$path d ifRoot ifNum]} {
@@ -847,15 +858,15 @@ foreach fn {/sbin/modprobe /usr/sbin/modprobe} {
 }
 Log "Module loader is $loader"
 
-set idfile $config(DriverIDPath)/new_id
+set idfile $config(driverIDPath)/new_id
 if {![file exists $idfile]} {
        if {$loader == ""} {
                Log "Can't do anymore without module loader; get \"modtools\"!"
                return
        }
-       Log "\nTry to load module \"$config(DriverModule)\""
-       if [catch {set result [exec $loader -v $config(DriverModule)]} err] {
-               Log " Running \"$loader $config(DriverModule)\" gave an error:\n  $err"
+       Log "\nTry to load module \"$config(driverModule)\""
+       if [catch {set result [exec $loader -v $config(driverModule)]} err] {
+               Log " Running \"$loader $config(driverModule)\" gave an error:\n  $err"
        } else {
                Log " Module was loaded successfully:\n$result"
        }
@@ -871,8 +882,8 @@ while {$i < 50} {
        incr i
 }
 if {$i < 50} {
-       Log "Try to add ID to driver \"$config(DriverModule)\""
-       SysLog "usb_modeswitch: add device ID $vid:$pid to driver \"$config(DriverModule)\""
+       Log "Try to add ID to driver \"$config(driverModule)\""
+       SysLog "usb_modeswitch: add device ID $vid:$pid to driver \"$config(driverModule)\""
        SysLog "usb_modeswitch: please report the device ID to the Linux USB developers!"
        if [catch {exec echo "$vid $pid ff" >$idfile} err] {
                Log " Error adding ID to driver:\n  $err"
@@ -882,7 +893,7 @@ if {$i < 50} {
 } else {
        Log " \"$idfile\" not found, check if kernel version is at least 2.6.27"
        Log "Fall back to \"usbserial\""
-       set config(DriverModule) usbserial
+       set config(driverModule) usbserial
        Log "\nTry to unload driver \"usbserial\""
        if [catch {exec $loader -r usbserial} err] {
                Log " Running \"$loader -r usbserial\" gave an error:\n  $err"
@@ -925,6 +936,15 @@ Log "No $id in bind_list"
 proc {AddToList} {name id} {
 
 set listfile /var/lib/usb_modeswitch/$name
+set oldlistfile /etc/usb_modeswitch.d/bind_list
+
+if {($name == "bind_list") && [file exists $oldlistfile] && ![file exists $listfile]} {
+       if [catch {file rename $oldlistfile $listfile} err] {
+               Log "Error renaming the old bind list file ($err)"
+               return
+       }
+}
+
 if [file exists $listfile] {
        set rc [open $listfile r]
        set buffer [read $rc]
@@ -980,14 +1000,14 @@ proc {CheckSuccess} {devdir} {
 global config usb flags
 set ifdir [file tail [IfDir 0]]
 
-if {[string length $config(TargetClass)] || [string length $config(Configuration)]} {
-       set config(TargetVendor) $usb(idVendor)
-       set config(TargetProduct) $usb(idProduct)
+if {[string length $config(targetClass)] || [string length $config(Configuration)]} {
+       set config(targetVendor) $usb(idVendor)
+       set config(targetProduct) $usb(idProduct)
 }
-Log "Check success of mode switch for max. $config(CheckSuccess) seconds ..."
+Log "Check success of mode switch for max. $config(checkSuccess) seconds ..."
 
 set expected 1
-for {set i 1} {$i <= $config(CheckSuccess)} {incr i} {
+for {set i 1} {$i <= $config(checkSuccess)} {incr i} {
        after 1000
        if {![file isdirectory $devdir]} {
                Log " Wait for device file system ($i sec.) ..."
@@ -1005,24 +1025,23 @@ for {set i 1} {$i <= $config(CheckSuccess)} {incr i} {
        if [string length $config(Configuration)] {
                if {$usb(bConfigurationValue) != $config(Configuration)} {continue}
        }
-       if [string length $config(TargetClass)] {
-               if {![regexp $usb($ifdir/bInterfaceClass) $config(TargetClass)]} {
+       if [string length $config(targetClass)] {
+               if {![regexp $usb($ifdir/bInterfaceClass) $config(targetClass)]} {
                        if {$config(class) != $usb($ifdir/bInterfaceClass} {
                                set expected 0
                        } else {continue}
                }
        }
-       if {![regexp $usb(idVendor) $config(TargetVendor)]} {
+       if {![regexp $usb(idVendor) $config(targetVendor)]} {
                if {![regexp $usb(idVendor) $config(vendor)]} {
                        set expected 0
                } else {continue}
        }
-       if {![regexp $usb(idProduct) $config(TargetProduct)]} {
+       if {![regexp $usb(idProduct) $config(targetProduct)]} {
                if {![regexp $usb(idProduct) $config(product)]} {
                        set expected 0
                } else {continue}
        }
-       # Arriving here means that device attributes have changed
        if $expected {
                Log " All attributes matched"
        } else {
@@ -1035,7 +1054,10 @@ for {set i 1} {$i <= $config(CheckSuccess)} {incr i} {
        }
        break
 }
-if {$i > 20} {return 0} else {return 1}
+if {$i > 20} {
+       return 0
+}
+return 1
 
 }
 # end of proc {CheckSuccess}
@@ -1122,51 +1144,12 @@ close $ch
 proc {CheckMBIM} {} {
 
 set kversion [exec uname -r]
-if [llength [glob -nocomplain /lib/modules/$kversion/kernel/drivers/net/usb/cdc_mbim*]] {return 1}
+if [file exists /lib/modules/$kversion/kernel/drivers/net/usb/cdc_mbim.ko] {return 1}
 if [file exists /sys/bus/usb/drivers/cdc_mbim] {return 1}
 return 0
 
 }
 
-proc {CheckQMI} {} {
-
-set kversion [exec uname -r]
-if [llength [glob -nocomplain /lib/modules/$kversion/kernel/drivers/net/usb/qmi_wwan*]] {return 1}
-if [file exists /sys/bus/usb/drivers/cdc_mbim] {return 1}
-return 0
-
-}
-
-proc {PantechAutoSwitch} {} {
-
-global config flags
-if {$config(PantechMode) == 3} {return 1}
-if {$config(PantechMode) == 1} {
-       if {"$config(vendor):$config(product)" == "10a9:6080"} {
-               set flags(config) [regsub {PantechMode *= *1} $flags(config) "PantechMode=2"]
-               Log " PantechMode changed to 2"
-               return 0
-       } elseif [CheckQMI] {
-               set flags(config) [regsub {PantechMode *= *1} $flags(config) "PantechMode=4"]
-               Log " PantechMode changed to 4"
-               return 0
-       } else {
-               return 1
-       }
-} else {return 0}
-
-}
-
-proc UnbindDriver {devdir ifdir} {
-
-set att $devdir/$ifdir/driver/unbind
-if [file exists $att] {
-       Log "Unbinding driver"
-       exec echo -n "$ifdir" > $att
-}
-
-}
-
 proc {LogAttributes} {} {
 
 global flags usb
@@ -1179,18 +1162,5 @@ if $flags(logging) {
 
 }
 
-proc {HasFF} {} {
-
-set i 0
-while {[set dir [IfDir $i]] != ""} {
-       set c [exec cat $dir/bInterfaceClass]
-       if {$c == "ff"} {return 1}
-       incr i
-}
-return 0
-
-}
-
-
 # The actual entry point
 Main $argv $argc
old mode 100644 (file)
new mode 100755 (executable)
index 91e5ac0..9081aba
@@ -1,8 +1,6 @@
 [Unit]
-Description=USB_ModeSwitch_%i
+Description=USB_ModeSwitch
 
 [Service]
 Type=oneshot
-ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-systemd %i
-#ExecStart=/bin/echo %i
-
+ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-systemd %I
old mode 100644 (file)
new mode 100755 (executable)
index 5b826d4..7c9ad5b
@@ -1,19 +1,18 @@
 .TH "USB_MODESWITCH_DISPATCHER" "1"
 .SH "NAME"
-usb_modeswitch_dispatcher - Linux wrapper for usb_modeswitch (not intended for direct invocation)
+usb_modeswitch_dispatcher - wrapper for usb_modeswitch, not intended for direct invocation.
 .SH "SYNOPSIS"
 .PP
 \fBusb_modeswitch_dispatcher\fR
 .SH "DESCRIPTION"
 .PP
 usb_modeswitch_dispatcher will do detailed device checking and will subsequently
-use the Linux-independent usb_modeswitch binary together with the selected device
-config file to switch the mode of certain USB devices.
+use the usb_modeswitch binary together with the selected device config file to
+switch the mode of certain USB devices.
 .PP
 If no drivers are taking care of the device after the mode switch, the dispatcher
-will try to load and bind the "option" serial driver to any USB interfaces with
-class 0xff, in order to make the device useable in case it is not recognized by that
-driver yet. This may or may not work.
+will try to load and bind the "option" serial driver, in order to make the device
+useable.
 .PP
 This program is called by udev and is not supposed to be called directly
 by the user.